// Set up the user interaction to manually show or hide the system UI. contentView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (TOGGLE_ON_CLICK) { mSystemUiHider.toggle(); } else { mSystemUiHider.show(); } } });
After launch, Android Studio suggested that I turn off the Android Device Monitor in order to integrate the output directly into the IDE. ## This file is automatically generated by Android Studio. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # # This file should *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. sdk.dir=C:\\Users\\<user>\\AppData\\Local\\Android\\android-studio\\sdk ndk.dir=D:\\ndk
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.11.0' } } apply plugin: 'android' android { compileSdkVersion 19 buildToolsVersion '19.1.0' defaultConfig { ndk { moduleName "sanangeles" cFlags "-DANDROID_NDK -DDISABLE_IMPORTGL" ldLibs "GLESv1_CM", "dl", "log" stl "stlport_static" } // This actual the app version code. Giving ourselves 1,000,000 values versionCode = 123 } buildTypes.debug.jniDebugBuild true productFlavors { x86 { ndk { abiFilter "x86" } // this is the flavor part of the version code. // It must be higher than the arm one for devices supporting // both, as x86 is preferred. versionCode = 3 } arm { ndk { abiFilter "armeabi-v7a" } versionCode = 2 } mips { ndk { abiFilter "mips" } versionCode = 1 } fat { // fat binary, lowest version code to be // the last option versionCode = 0 } } // make per-variant version code applicationVariants.all { variant -> // get the single flavor def flavorVersion = variant.productFlavors.get(0).versionCode // set the composite code variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode } }
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.12.+' } } apply plugin: 'android' android { compileSdkVersion 19 buildToolsVersion '20.0.0' defaultConfig { ndk { moduleName "sanangeles" cFlags "-DANDROID_NDK -DDISABLE_IMPORTGL" ldLibs "GLESv1_CM", "dl", "log" stl "stlport_static" } // This actual the app version code. Giving ourselves 1,000,000 values versionCode = 123 } buildTypes.debug.jniDebugBuild true productFlavors { x86 { ndk { abiFilter "x86" } // this is the flavor part of the version code. // It must be higher than the arm one for devices supporting // both, as x86 is preferred. versionCode = 3 } arm { ndk { abiFilter "armeabi-v7a" } versionCode = 2 } mips { ndk { abiFilter "mips" } versionCode = 1 } fat { // fat binary, lowest version code to be // the last option versionCode = 0 } } // make per-variant version code applicationVariants.all { variant -> // get the single flavor def flavorVersion = variant.productFlavors.get(0).versionCode // set the composite code variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode } }
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:0.12.+' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() } }
apply plugin: 'com.android.application' android { compileSdkVersion 20 buildToolsVersion "20.0.0" defaultConfig { applicationId "com.example.markedone.myapp" minSdkVersion 15 targetSdkVersion 20 versionCode 1 versionName "1.0" } buildTypes { release { runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) // You must install or update the Support Repository through the SDK manager to use this dependency. //compile 'com.android.support:support-v4:19.+' compile 'com.android.support:support-v4:20.+' }
compileSdkVersion 20
compileSdkVersion 19
defaultConfig { applicationId "com.example.markedone.myapp" minSdkVersion 15 targetSdkVersion 19 versionCode 1 versionName "1.0" ndk { moduleName "myapp" cFlags "-DANDROID_NDK" ldLibs "log" stl "stlport_static" } }
NDK settings include buildTypes { release { runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug.jniDebugBuild true }
productFlavors { x86 { ndk { abiFilter "x86" } // this is the flavor part of the version code. // It must be higher than the arm one for devices supporting // both, as x86 is preferred. versionCode = 3 } arm { ndk { abiFilter "armeabi-v7a" } versionCode = 2 } mips { ndk { abiFilter "mips" } versionCode = 1 } fat { // fat binary, lowest version code to be // the last option versionCode = 0 } }
// make per-variant version code applicationVariants.all { variant -> // get the single flavor def flavorVersion = variant.productFlavors.get(0).versionCode // set the composite code variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode }
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) // You must install or update the Support Repository through the SDK manager to use this dependency. compile 'com.android.support:support-v4:19.+' }
apply plugin: 'com.android.application' android { compileSdkVersion 19 buildToolsVersion "20.0.0" defaultConfig { applicationId "com.example.markedone.myapp" minSdkVersion 15 targetSdkVersion 19 versionCode 1 versionName "1.0" ndk { moduleName "myapp" cFlags "-DANDROID_NDK" ldLibs "log" stl "stlport_static" } } buildTypes { release { runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug.jniDebugBuild true } productFlavors { x86 { ndk { abiFilter "x86" } // this is the flavor part of the version code. // It must be higher than the arm one for devices supporting // both, as x86 is preferred. versionCode = 3 } arm { ndk { abiFilter "armeabi-v7a" } versionCode = 2 } mips { ndk { abiFilter "mips" } versionCode = 1 } fat { // fat binary, lowest version code to be // the last option versionCode = 0 } } // make per-variant version code applicationVariants.all { variant -> // get the single flavor def flavorVersion = variant.productFlavors.get(0).versionCode // set the composite code variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode } sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jni/'] } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) // You must install or update the Support Repository through the SDK manager to use this dependency. compile 'com.android.support:support-v4:19.+' }
#pragma once #include <jni.h> #ifdef __cplusplus extern "C" { #endif JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz); #ifdef __cplusplus } #endif
#pragma once
- instead of the standard (# ifndef / # define / # endif) protection against re-activation. Now #pragma once
is understood by most C ++ compilers.#include <jni.h>
- #include <jni.h>
JNI header so that you can use the types declared there.#ifdef __cplusplus ... #endif
- the code inside will be compiled only in C ++ (but not in C).extern "C" { ... }
- we get rid of name mangling (what it is and why, it is well described here ).JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz);
- declaration of the function that we will implement.JNIEnv* env, jclass clazz
- required parameters passed from Java.JNIEnv* env
- a pointer to an object, which is a JNI environment.jclass clazz
is the class to which the native method declaration in Java belongs. Here we need to make a reservation that jclass clazz is for a static native ( static native ) method. For a non-static method, you will need to write a jobject obj
. #include <android/log.h> #include <string> #include "myapp.h" JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz) { std::string tag("GREETING"); std::string message("Hello from C++!"); __android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%s", message.c_str()); std::string jniMessage("Hello from JNI!"); return env->NewStringUTF(jniMessage.c_str()); }
#include <android/log.h>
- #include <android/log.h>
log, for which we even added the library ( ldLibs "log" )#include - std::string, STL.
#include "myapp.h"
- connect our header file.JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz) { ... } - , "myapp.h".
std::string tag("GREETING"); std::string message("Hello from C++!");
- create lines for output to the log.__android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%s", message.c_str());
- output to log. Please note that you need to specify 4 parameters: the type of message in the log, the tag, the format of the string, and, finally, the message itself.std::string jniMessage("Hello from JNI!");
- a string that we will pass in java.return env->NewStringUTF(jniMessage.c_str());
- return value, using JNIEnv, create a jstring from a C-string. Please note that we do not need the construction of the form (*env)->
, since we write in C ++, and not in C. package com.example.markedone.myapp; import com.example.markedone.myapp.util.SystemUiHider; import android.annotation.TargetApi; import android.app.Activity; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.view.MotionEvent; import android.view.View; /** * An example full-screen activity that shows and hides the system UI (ie * status bar and navigation/system bar) with user interaction. * * @see SystemUiHider */ public class FullscreenActivity extends Activity { /** * Whether or not the system UI should be auto-hidden after * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds. */ private static final boolean AUTO_HIDE = true; /** * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after * user interaction before hiding the system UI. */ private static final int AUTO_HIDE_DELAY_MILLIS = 3000; /** * If set, will toggle the system UI visibility upon interaction. Otherwise, * will show the system UI visibility upon interaction. */ private static final boolean TOGGLE_ON_CLICK = true; /** * The flags to pass to {@link SystemUiHider#getInstance}. */ private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION; /** * The instance of the {@link SystemUiHider} for this activity. */ private SystemUiHider mSystemUiHider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fullscreen); final View controlsView = findViewById(R.id.fullscreen_content_controls); final View contentView = findViewById(R.id.fullscreen_content); // Set up an instance of SystemUiHider to control the system UI for // this activity. mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS); mSystemUiHider.setup(); mSystemUiHider .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() { // Cached values. int mControlsHeight; int mShortAnimTime; @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) public void onVisibilityChange(boolean visible) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { // If the ViewPropertyAnimator API is available // (Honeycomb MR2 and later), use it to animate the // in-layout UI controls at the bottom of the // screen. if (mControlsHeight == 0) { mControlsHeight = controlsView.getHeight(); } if (mShortAnimTime == 0) { mShortAnimTime = getResources().getInteger( android.R.integer.config_shortAnimTime); } controlsView.animate() .translationY(visible ? 0 : mControlsHeight) .setDuration(mShortAnimTime); } else { // If the ViewPropertyAnimator APIs aren't // available, simply show or hide the in-layout UI // controls. controlsView.setVisibility(visible ? View.VISIBLE : View.GONE); } if (visible && AUTO_HIDE) { // Schedule a hide(). delayedHide(AUTO_HIDE_DELAY_MILLIS); } } }); // Set up the user interaction to manually show or hide the system UI. contentView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (TOGGLE_ON_CLICK) { mSystemUiHider.toggle(); } else { mSystemUiHider.show(); } } }); // Upon interacting with UI controls, delay any scheduled hide() // operations to prevent the jarring behavior of controls going away // while interacting with the UI. findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Trigger the initial hide() shortly after the activity has been // created, to briefly hint to the user that UI controls // are available. delayedHide(100); } /** * Touch listener to use for in-layout UI controls to delay hiding the * system UI. This is to prevent the jarring behavior of controls going away * while interacting with activity UI. */ View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (AUTO_HIDE) { delayedHide(AUTO_HIDE_DELAY_MILLIS); } return false; } }; Handler mHideHandler = new Handler(); Runnable mHideRunnable = new Runnable() { @Override public void run() { mSystemUiHider.hide(); } }; /** * Schedules a call to hide() in [delay] milliseconds, canceling any * previously scheduled calls. */ private void delayedHide(int delayMillis) { mHideHandler.removeCallbacks(mHideRunnable); mHideHandler.postDelayed(mHideRunnable, delayMillis); } }
static { System.loadLibrary("myapp"); } private static native String stringFromJNI();
Here, the library is loaded first and then the declaration of the stringFromJNI method, which corresponds to our function in C ++. Please note that it is declared as static (this affects the (jclass or jobject) as the second parameter of the C ++ function) and native. You do not need to implement the native method, we have already done this in C ++, and the rest is JNI will do for us.import android.widget.Button;
View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (AUTO_HIDE) { delayedHide(AUTO_HIDE_DELAY_MILLIS); } return false; } };
return false
. View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (AUTO_HIDE) { delayedHide(AUTO_HIDE_DELAY_MILLIS); } final String message = stringFromJNI(); final Button button = (Button)findViewById(R.id.dummy_button); final String actualText = button.getText().toString(); if(message.equals(actualText)) { button.setText("Dummy Button"); } else { button.setText(message); } return false; } };
final String message = stringFromJNI();
- get a string from C ++. The call to the native method is what it was all about.final Button button = (Button)findViewById(R.id.dummy_button);
- find the button object.final String actualText = button.getText().toString();
— .if(message.equals(actualText))
— , C++, .button.setText("Dummy Button");
— , Dummy Button.button.setText(message);
— , , C++. package com.example.markedone.myapp; import com.example.markedone.myapp.util.SystemUiHider; import android.annotation.TargetApi; import android.app.Activity; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.view.MotionEvent; import android.view.View; import android.widget.Button; /** * An example full-screen activity that shows and hides the system UI (ie * status bar and navigation/system bar) with user interaction. * * @see SystemUiHider */ public class FullscreenActivity extends Activity { static { System.loadLibrary("myapp"); } private static native String stringFromJNI(); /** * Whether or not the system UI should be auto-hidden after * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds. */ private static final boolean AUTO_HIDE = true; /** * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after * user interaction before hiding the system UI. */ private static final int AUTO_HIDE_DELAY_MILLIS = 3000; /** * If set, will toggle the system UI visibility upon interaction. Otherwise, * will show the system UI visibility upon interaction. */ private static final boolean TOGGLE_ON_CLICK = true; /** * The flags to pass to {@link SystemUiHider#getInstance}. */ private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION; /** * The instance of the {@link SystemUiHider} for this activity. */ private SystemUiHider mSystemUiHider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fullscreen); final View controlsView = findViewById(R.id.fullscreen_content_controls); final View contentView = findViewById(R.id.fullscreen_content); // Set up an instance of SystemUiHider to control the system UI for // this activity. mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS); mSystemUiHider.setup(); mSystemUiHider .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() { // Cached values. int mControlsHeight; int mShortAnimTime; @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) public void onVisibilityChange(boolean visible) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { // If the ViewPropertyAnimator API is available // (Honeycomb MR2 and later), use it to animate the // in-layout UI controls at the bottom of the // screen. if (mControlsHeight == 0) { mControlsHeight = controlsView.getHeight(); } if (mShortAnimTime == 0) { mShortAnimTime = getResources().getInteger( android.R.integer.config_shortAnimTime); } controlsView.animate() .translationY(visible ? 0 : mControlsHeight) .setDuration(mShortAnimTime); } else { // If the ViewPropertyAnimator APIs aren't // available, simply show or hide the in-layout UI // controls. controlsView.setVisibility(visible ? View.VISIBLE : View.GONE); } if (visible && AUTO_HIDE) { // Schedule a hide(). delayedHide(AUTO_HIDE_DELAY_MILLIS); } } }); // Set up the user interaction to manually show or hide the system UI. contentView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (TOGGLE_ON_CLICK) { mSystemUiHider.toggle(); } else { mSystemUiHider.show(); } } }); // Upon interacting with UI controls, delay any scheduled hide() // operations to prevent the jarring behavior of controls going away // while interacting with the UI. findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Trigger the initial hide() shortly after the activity has been // created, to briefly hint to the user that UI controls // are available. delayedHide(100); } /** * Touch listener to use for in-layout UI controls to delay hiding the * system UI. This is to prevent the jarring behavior of controls going away * while interacting with activity UI. */ View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (AUTO_HIDE) { delayedHide(AUTO_HIDE_DELAY_MILLIS); } final String message = stringFromJNI(); final Button button = (Button)findViewById(R.id.dummy_button); final String actualText = button.getText().toString(); if(message.equals(actualText)) { button.setText("Dummy Button"); } else { button.setText(message); } return false; } }; Handler mHideHandler = new Handler(); Runnable mHideRunnable = new Runnable() { @Override public void run() { mSystemUiHider.hide(); } }; /** * Schedules a call to hide() in [delay] milliseconds, canceling any * previously scheduled calls. */ private void delayedHide(int delayMillis) { mHideHandler.removeCallbacks(mHideRunnable); mHideHandler.postDelayed(mHideRunnable, delayMillis); } }
Source: https://habr.com/ru/post/228365/
All Articles