Attention! Is facing pure pure pure small white!

This is a little white note that is the simplest step to implement JNI (save as much as you can, and I won’t do anything complicated).

JNI (Java Native Interface) simply means allowing Java programs running on the JVM to call Native code (C/C++ or even assembly language code).

Let’s cut the crap.

Here, a very simple requirement is implemented. Click the button and call the method on the Java side to call the method on the C side. The C side returns a string to the Java side and displays it on the interface, as shown below:

It is achieved by the following steps:

1. Create an Android project

2. Declare native methods

3. Implement native methods

4. Run the ndk-build command to generate the so file

5. Call native methods on the Java side

How’s that? Does it look fresh?

Let’s do it step by step.


1. There’s nothing to say about new Android projects, just follow the normal steps.

2. Declare Native methods

Public class JniTest {static {// load the jni so library, jni-test is the name of the final output of the so, you can call it another name, but it must be the same as the name of the final so library. // (so file is automatically preceded by lib) system.loadLibrary ("jni-test"); } public native String getStrFromNative(); }Copy the code

I’m just creating a separate new class here, JniTest, which has a method called getStrFromNative that returns a String. Notice that the class also has a static block inside it, which is required before calling native methods, because you have to load the so file in to call its methods.

3. Implement native methods

Create a new jni folder in the main directory, and create three new files: Android.mk, application. mk, and test.c.

The Android. Mk code is as follows:

LOCAL_PATH := $(call my-dir) // Set working directory, My-dir will return the directory containing android. mk include $(CLEAR_VARS) LOCAL_MODULE := jni-test LOCAL_SRC_FILES := test.c // Specify the c /C++ source file included in the compilation $(BUILD_SHARED_LIBRARY)Copy the code

Line 6 corresponds to line 7 of the JniTest class above (both jNI-test)

Line 10 corresponds to the name of the third file.

Then add the following code to the Android block of your app’s build.gradle file:

externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }
Copy the code

The Application. Mk code is as follows:

APP_ABI := all
Copy the code

It’s simple, just one line of code. The so file used to specify which platforms to generate, set to all, will generate 4 folders as shown in the following figure, corresponding to 4 different platforms:

I tried to change “all” to “Armeabi” before, but I reported a puzzling error and failed to solve it. I don’t know the reason yet, I will try again later.

Finally, the test.c code:

#include<jni.h> jstring Java_com_example_jnitest2_JniTest_getStrFromNative(JNIEnv *env,jobject thiz){ return (*env)->NewStringUTF(env," I am a string from Native "); }Copy the code

Returns a string. Note that the method return value jString corresponds to the Java String, and the method name Java_ complete package name _ class name _ method name. There is also the env pointer, which is simply a pointer to the JNI environment and can be used to access interface methods provided by JNI.

4. Run the ndk-build command to generate the so file

You need to install the NDK on your computer and configure the environment variables.

Then, in a command line window, CD to the parent directory of jni (in this case……) \app\ SRC \main), and then run the ndk-build command to export the so file.

Two folders are then generated in the parent directory of JNI (libs- contains so files for each platform, obj- temporary intermediate files, obj is deletable)

Then don’t forget to add code to your App’s Build. gradle Android block:

sourceSets{
        main{
            jniLibs.srcDirs=['libs']
        }
    }
Copy the code

If you do not add it, the following error will be reported.

Finally, I changed the generated liBS directory to jniLibs (in addition to directly changing to jniLibs, you can also create a jniLibs folder under the same directory as LIBS and copy the folder containing the SO files of each platform into it).

Let me explain why LIBS was directly changed to jniLibs.

If I create a new liBS folder in another place, it is also ok to copy the SO file in the generated LIBS folder (that is, I need to change the third line in the above code to the corresponding path), but there is a problem that when I change the native method, I have to re-execute the Ndk-build command to re-export the so file (here I want to change the returned string), which is a hassle, whereas if I had just changed the libs folder generated by executing the Ndk-build command to jniLibs, I wouldn’t have to re-export the so file, and I don’t know why.

5. Call native methods on the Java side

This is easy, just like calling a normal method.

String str = new JniTest().getStrFromNative();
tv.setText(str);
Copy the code

So what I’m doing here is I’m displaying the string that I got from my Native in a TextView.


Reference:

Blog.csdn.net/wzhseu/arti…

Chapter 14 in Exploring the Art of Android Development


Welcome to my official account ~ (MCLzone)