Java and C of Android JNI call each other

Overview

What is JNI

JNI is the abbreviation of Java Native Interface, which provides several APIs to communicate between Java and other languages ​​(mainly C & C++ ). Since Java 1.1, the JNI standard has become part of the Java platform, which allows Java code to interact with code written in other languages.

What is NDK

NDK is an acronym for Native Development Kit. It is part of the SDK (software development kit) software development kit, but usually requires a separate download. See About NDK for details .

Advantages and disadvantages of JNI

  • advantage:
    1. Interact with other languages, each according to his own strengths.
    2. Increase the difficulty of decompilation
  • shortcoming:
    1. Losing the advantage of Java's cross-platform

Java calls C

  1. moduleunder configurationbuild.gradle

    android {
       compileSdkVersion 25
       buildToolsVersion "25.0.0"
       defaultConfig {
           ...
           ndk {
               moduleName "CallEachOther" //编译生成so库的名字,要和loadLibrary里面的参数一致
               abiFilters "armeabi","armeabi-v7a","x86","x86_64","mips","arm64-v8a","mips64"//编译支持的平台
           }
       }
    }
  2. new Javaclass

    public class JNITest_Java {
       static {
           System.loadLibrary("CallEachOther");
       }
    
       public native String getStringFromC();
    }

    System.loadLibraryThe parameter in here is build.gradlethe value moduleNamein , ie CallEachOther. Here we define a nativemethod getStringFromC(). For now, the Javaend can temporarily come to an end. Next, it's time to generate the header files.

  3. generate .hheader file

    1. Open ASthe built-in Terminal, cd src/main/javacommand to enter the Javafolder. ps: use cmdthe same effect as the command

    2. Enter the command javah 完整包名.类名. E.g:javah com.dongyk.jnitest.JNITest_Java。

      At this point, it will be Javagenerated in the directory 包名_类名.h. AS2.2.2It will turn red when you open it, it looks like it ASis bug. But it does not affect the normal compilation.

  4. Create a new folder in the maindirectory , New .jniJniTestC.c

    
    #include <stdio.h>
    
    
    #include <stdlib.h>
    
    
    #include "com_dongyk_jnitest_JNITest_Java.h"
    
    
    JNIEXPORT jstring JNICALL Java_com_dongyk_jnitest_JNITest_1Java_getStringFromC(JNIEnv * env, jobject jobj){
       char* str = "I come from C";
       return (*env)->NewStringUTF(env,str);
    };

    There are certain rules for names of methods here. Format: Java_包名_类名. The method name is too long. It is recommended to copy it from the newly generated .hfile. Here is a brief explanation of this method:

    1. JNIEnv * env envThe pointer points to a table of function pointers.
    2. jobject jobjJavaPoints to the object instantiated in code Java, equivalent to the this pointer.
    3. (*env)->NewStringUTFRepresents calling a env#NewStringUTF()method.
    4. Finally return "I come from C".
  5. called in MainActivity.

    public class MainActivity extends AppCompatActivity {
       private TextView tv;
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           tv = (TextView) findViewById(R.id.tv);
           String result = new JNITest_Java().getStringFromC();
           tv.setText(result);
       }
    }

C calls Java

  1. Javaadd method to class

    public class JNITest_Java {
        static {
            System.loadLibrary("JavaCallC");
        }
    
        public native String getStringFromC();
    
        public native int callAdd();
    
        public int add(int a, int b) {
            Log.i("TAG","add was called");
            return a + b;
        }
    }

    Understand the process first. The code called at the Javalayer must be the Javacode. A method is written here . When this method is called, the calling callAdd()method is notified . This process is first as a concrete implementation of the method, and the method is called in it. Then call the command to generate the header file.Cadd()CJavaCJavajavah.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    
    #include <jni.h>
    
    /* Header for class com_dongyk_jnitest_JNITest_Java */
    
    
    #ifndef _Included_com_dongyk_jnitest_JNITest_Java
    
    
    #define _Included_com_dongyk_jnitest_JNITest_Java
    
    
    #ifdef __cplusplus
    
    extern "C" {
    
    #endif
    
    /*
     * Class:     com_dongyk_jnitest_JNITest_Java
     * Method:    getStringFromC
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL ava_com_dongyk_jnitest_JNITest_1Java_getStringFromC
    (JNIEnv
    *, jobject);
    
    /*
     * Class:     com_dongyk_jnitest_JNITest_Java
     * Method:    callAdd
     * Signature: ()V
     */
    JNIEXPORT jint JNICALL Java_com_dongyk_jnitest_JNITest_1Java_callAdd
    (JNIEnv *, jobject);
    
    
    #ifdef __cplusplus
    
    }
    
    #endif
    
    
    #endif
    
  2. .cThe specific implementation of the main function

    JNIEXPORT jint JNICALL Java_com_dongyk_jnitest_JNITest_1Java_callAdd(JNIEnv *env, jobject jobj){
        // 得到字节码
        jclass clazz = (*env)->FindClass(env,"com/dongyk/jnitest/JNITest_Java");
        // 得到方法 
        jmethodID jmethodid = (*env)->GetMethodID(env,clazz,"add","(II)I");
        // 实例化类
        jobject jobject = (*env)->AllocObject(env,clazz);
        // 调用方法
        return (*env)->CallIntMethod(env,jobject,jmethodid,3,5);
    };

    (*env)->GetMethodID中The last parameter is the method signature. Because Javamethod overloading is supported, but these overloaded methods Jniare named the same in , the method signature is introduced to distinguish function overloading. Get the method signature: first rebuliddownload the project, cd build\intermediates\classes\debugthen use javap -s 包名/类名it to get all the method signatures. E.g:javap -s com/dongyk/jnitest/JNITest_Java

    public int add(int, int);
       descriptor: (II)I

    descriptorThe corresponding is the method signature. Of course. There are FindClass、GetMethodIDother methods in it, see XXX\sdk\ndk-bundle\platforms\android-xx\arch-arm\usr\include\jni.h for details.

  3. called in MainActivity.

    public class MainActivity extends AppCompatActivity {
        private TextView tv;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv = (TextView) findViewById(R.id.tv);
            int result = new JNITest_Java().callAdd();
            tv.setText(result+"");
        }
    }

    So far, a Jnismall entry for beginners has been Demowritten~

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325543757&siteId=291194637