“This is the 27th day of my participation in the August Gwen Challenge.
- The first step is to set the NDK path and configure the corresponding development environment
- Set javah, Javap, and dk-build shortcuts in External Tools. (This step is mainly to simplify command line input. Native command line is also available.)
Javah parameter configuration (direct copy) : Program:
\bin\javah.exe Parameters: -classpath . -jni -o
/src/main/jni/
Working directory:
\src\main\Java Another way to write Parameters: -classpath . -jni -d
/src/main/jni
Javap Parameters: * Program: JDKPathJDKPathJDKPath\bin\javap Parameters: -s -p FileClassFileClassFileClass Working directory: ModuleFileDirModuleFileDirModuleFileDir\build\intermediates\classes\debug
Dk-build parameter configuration (direct copy) :
Program: D:\Android_NDK\android-ndk-r11b\ndk-build.cmd
Working directory:
\src\main
- The third step is to create a Java class that references the link library to be created, along with the necessary local methods
static { System.loadLibrary("MyJni"); } public String getStringFromNative(); Public native String getString_From_c();Copy the code
- Step 4 Use the javah shortcut keys configured earlier to quickly generate the. H header file
The JNI directory is automatically created and the header files are generated
- Step 5 Start writing C/C++ code in the JNI directory by referring to the header file! []
Note:
Jni folder appears as CPP name when project structure is switched to Android state!
Jni folder is displayed when switching to Project!!
The diagram below:
Add the following code:
- Step 6 Configure Gradle
NDK {moduleName "MyJni"// so library name ldLibs "log"// connect to the library, can have multiple abiFilters "armeabi","armeabi-v7a","x86"// specify so library running CPU architecture, Armeabi - v7A arm64-V8a x86 x86_64 MIPS miPS64 Armeabi -v7a arm64-V8A x86 x86_64 MIPS miPS64Copy the code
The Android.mk file is automatically generated by clicking on the Androidstudio menu bar Build ->ReBuildProject
Copy the android. mk file to the main/jni folder and right-click ->External Tools -> dk-build to generate.so file!!
Next, add it to the project’s gradle.properties file
android.useDeprecatedNdk=true
Copy the code
- Step 7 Run Java code to retrieve the C library
Matters needing attention
-
Load the filename specified by the generated dynamic library (system.loadlibrary (“MyJni”);) (NDK {moduleName “MyJni”} in build.gradle) and LOCAL_MODULE := MyJni in Android.mk.
-
Exception message does not support c++
Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio. Please switch to a supported build system. Consider using CMake or ndk-build integration. For more information, go to: https://d.android.com/r/studio-ui/add-native-code.html#ndkCompile To get started, you can use the sample ndk-build script the Android plugin generated for you at: E:\IT\youban\module_c++\build\intermediates\ndk\release\Android.mk Alternatively, you can use the experimental plugin: https://developer.android.com/r/tools/experimental-plugin.html To continue using the deprecated NDK compile for another 60 days, set android.deprecatedNdkCompileLease=1570504380180 in gradle.properties Copy the code
Solution: Add the following configuration to build.gradle:
Android {// add the following information, Link C++ Project with Gradle option is no longer displayed when right-click the Project; // externalNativeBuild { // ndkBuild { // path file('src/main/jni/Android.mk') // } // } }Copy the code
Attached :C tune Java code
The code in Java is as follows:
static { System.loadLibrary("MyJni"); } public void show(){system.out.println ("hahaha C++ call me ");} public void show(){system.out.println ("hahaha C++ call me "); }Copy the code
The code in C is as follows:
Jclass dpclazz = (*env)->FindClass(env, "com/insworks/module_ccc/CCCTestActivity"); If (dpclazz == 0) {return (*(*env)).NewStringUTF(env, "NDK did not find specified class "); } //2 method1 = (*env)->GetMethodID(env, dpclazz, "show", "()V"); If (method1 == 0) {return (*(*env)).NewStringUTF(env, "NDK did not find method "); Jobject1 = (*env)->AllocObject(env, dpclazz); (*env)->CallVoidMethod(env, jobject1, method1);Copy the code
Matters needing attention:
- Native methods are called differently in C and C++, for example:
/* C */
return (*env)->NewStringUTF(env, "Hello World");
/* C++ */
return env->NewStringUTF("Hello World");
Copy the code
In C, JNIEnv is a pointer to the JNINativeInterface structure and must be dereferenced to use it. And the first argument is env, and if you’ve learned C and C++, C is a procedural language, NewStringUTF is just a pointer to a function, and you don’t know who’s calling it, so you pass env, and C++ doesn’t, because C++ is an object-oriented language, so I won’t explain that
2. Call C functions or variables in C++
// extern "C" // {// #include "cexample.h "; // extern "C" // {// #include" cexample.h "; / /}Copy the code
3. The name of so file
The LOCAL_MODULE in the android. mk file determines the name of the so file. The LOCAL_MODULE name can be changed manually or configured in build.gradle:
NDK {// moduleName "native_datahelp"}Copy the code
4. About the System. LoadLibrary ();
How can loadLibrary run successfully with inconsistent names?
At present, the self-test found that many compiled SO libraries appeared in the build file may be the reason that the old SO library was not cleared in time. We can study the build folder, which contains a lot of secrets
5. The ndk-build command runs successfully without executing the command
After C/C++ source files are changed, they will be automatically called nk-build and compiled to generate a new SO inventory in the build folder, which can be copied and used directly. Nk-build will generate a formal SO library, which is the same as APK packaging The Android.mk file must be present, otherwise the so library cannot be compiled, nor can the source be compiled to identify the file