The first part of the preface explains the basic process of JNI development through a simple example, and finally compiles its own SO file. This part mainly introduces how to introduce the third party so file and make calls

Zero base takes you to eat JNI Family bucket (1)

Zero base takes you to eat JNI Family bucket (3)

How to call a method in a third party SO?

Through the last we know, from the Java layer to call native methods, registered either static or dynamic registration, but in either, two methods, must need to establish a channel relationship between static registration needs corresponding to the method name, dynamically register need to binding of two methods, are all need to know the package name, but the problem is coming, So how do I call a method in a third party SO in my project? There are actually two ways to name your own project package:

  • If the third party provides so file and SDK JAR package file at the same time, in fact, it does not need to do too much operation itself. It directly calls the methods in the API, and then maps the SDK with native methods internally. We just need to import the SO library file and put it in the specified location, usually in the jniLibs directory. This allows the SDK to communicate with the native layer.
  • The above method is generally applicable to the integration of third-party services, such as Autonavi, Alliance, etc., which is relatively limited and can only be operated under the limits of SDK. If it needs to be extended to a certain extent or no one provides you with SDK package (such as some internal libraries of your company often have this situation), In this case, you need to write the local method to communicate the mapping, after you need to import the SO

2. Associate third-party SO libraries

The first method above is not mentioned. Generally, you can directly call the SDK. Let’s look at the second method directly, which is roughly divided into the following steps:

  • Import the third party SO file and put it in the specified directory, usually under the jniLibs directory
  • Write cMakelists.txt file, introduce so library and correlate
  • When writing native methods, the package name must be the same as the corresponding package name in so

Let’s use the so generated from the example in the previous section. Let’s call and copy the SO from the build in the following location. Here we can use the ARM architecture, one is 64-bit, one is 32-bit

And then we’re going to put it into a new project that we’re going to create, and we’re going to rename so here to avoid confusion

Then we need to specify the so file directory in build.gradle

sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = ['src\\main\\jniLibs']
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"}}Copy the code

Then, since there is no need to generate the so library itself, the native-lib in cmakelists.txt can be removed, and we add the so library we want to introduce and associate with it


# Defines the minimum version number supported by cmakeCmake_minimum_required (VERSION 3.4.1 track)Add lib2 library and define it as an import
add_library(lib2 SHARED IMPORTED)

ANDROID_ABI will select the so file based on its CPU architecture
set_target_properties( lib2
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libdata.so)
Find dependencies from the system, can add more than one
find_library( For example, find the system log library liblog.so
              log-lib

              The libnative-lib.so library is named log, just as the libnative-lib.so library is named native-lib
              log )
Copy the code

The CMakeLists file will load the libdata.so file when it is executed.

As a final step, write the local method and create a new class

package com.example.taolin.jni_project;

public class NativeHelper {
    static {
        System.loadLibrary("data");
    }
    public static native String stringFromJNI();
    public static  native int add(int a,int b);
}
Copy the code

The main package name, to be consistent with the so, is also the dynamic registration code in the previous article, pasted here

// registerMethod(JNIEnv *env) {jclass CLZ = env->FindClass("com/example/taolin/jni_project/NativeHelper");
    if (clz == NULL) {
        LOGD("con't find class: com/example/taolin/jni_project/NativeHelper");
    }
    JNINativeMethod jniNativeMethod[] = {{"stringFromJNI"."()Ljava/lang/String;",                       (void *) backStringToJava},
                                         {"add"."(II)I",                                      (void *) addNum},};
    return env->RegisterNatives(clz, jniNativeMethod,
                                sizeof(jniNativeMethod) / sizeof(jniNativeMethod[0]));
}
Copy the code

In this way, when the call is made, the corresponding class can be found and the Java layer method and the Native layer method can be associated for communication

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(NativeHelper.stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */

}
Copy the code

I will not cut the concrete picture, also can successfully display the string, so called the external so method, you are done!

The Jni syntax and the more complex interaction between the Java layer and native layer. How to transfer objects? How does the Native layer operate Java layer classes? And so on.

Have the new idea and the question old brother can leave a message to discuss together oh, slipped slipped ~