AS開發JNI步驟

1. 安裝配置NDK  
    1). 解壓NDK的zip包到非中文目錄  
    2). 配置path : 解壓後NDK的根目錄----->ndk-build  
  
2. 給AS配置關聯NDK  
    1). local.properties中添加配置  
     ndk.dir=D\:\\android-ndk\\ndk-bundle
    2). gradle.properties中添加配置 ,若是是最新的ndk,則不須要以下配置
        android.useDeprecatedNdk=true  
  
3. 編寫native方法:  
    public class JNIS {  
        public native String helloJNI();  
    }  
  
4. 定義對應的JNI  
    1). 在main下建立jni文件夾  
    2). 生成native方法對應的JNI函數聲明頭文件: 命令窗口中, 進入java文件夾  
            執行命令: javah com.atguigu.jnitests2.JNIS  
            生成頭文件: com_atguigu_jnitests2_JNIS.h  
            函數聲明: JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI(JNIEnv *, jobject); 這時生成的.h頭文件應該在java文件夾下面。
    著:若是在java目錄下編譯找不到編譯的文件,能夠到debug目錄下編譯,此時生成的.h頭文件在debug目錄下面。
    3). 將生成的頭文件轉移到jni文件夾下  
    4). 在jni下定義對應的函數文件: test.c  
        #include "com_atguigu_jnitests2_JNIS.h"  
        JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI  
        (JNIEnv * env, jobject jobj) {  
            return (*env)->NewStringUTF(env, "Hello from C");  
        }  
    5). 在jni文件夾下建立一個空的C文件: util.c  
        說明: 這是AS的bug, 必須至少2個C文件才能經過編譯  
  
5. 在該項目下的build.gradle配置生成的so名稱和支持的cpu類型  在android中
        defaultConfig {  
            ndk{  
            moduleName "HelloJni" //so文件: lib+moduleName+.so  
            abiFilters "armeabi", "armeabi-v7a", "x86" //cpu的類型  
            }  
        }  
6. 編譯生成不一樣平臺下的動態連接文件  
    1). 執行rebuild, 生成so文件  
    2). so文件目錄: build\intermediates\ndk\debug\lib\.....  
7. 調用native方法:  
    1). 在native方法所在的類中加載so文件  
            static {  
            System.loadLibrary("HelloJni");  
            }  
    2). 在Activity中調用native方法:  
            String result = new JNIS().helloJNI();  
        Log.e("TAG", "result="+result);  java

 

步驟如上,下面是經過jni和java交互,java調用jni,而c裏面訪問java的私有屬性,公有屬性,靜態屬性以及公有方法,靜態方法和父類的方法。android

代碼:ide

package aes.example.com.aesjnidemo.demo;

public class JniOperate extends SuperJni{

    public int num = 100;
    public static String staticField = "staticFiled in java";
    private int age = 20;
    private String test = "java";
    public static int testStatic = 90;

    public native int addNum();
    public native void accessStaticFiled();
    public native void accessPrivateField();
    public native void accessPublicMethod();
    public native void accessStaticMethod();
    public native String accessSuperMethod();

    public void testPublicMethod(String para) {
        this.test = para;
    }

    public static void testStaticMethod() {
        testStatic = 101;
    }

    public int getAge() {
        return age;
    }

    public String getTest() {
        return test;
    }

    static {
        System.loadLibrary("jni_opearte");
    }
}

 

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class aes_example_com_aesjnidemo_demo_JniOperate */

#ifndef _Included_aes_example_com_aesjnidemo_demo_JniOperate
#define _Included_aes_example_com_aesjnidemo_demo_JniOperate
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    addNum
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_addNum
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessStaticFiled
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticFiled
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPrivateField
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPrivateField
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPublicMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPublicMethod
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessStaticMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticMethod
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessSuperMethod
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessSuperMethod
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
#include <string.h>
#include "aes_example_com_aesjnidemo_demo_JniOperate.h"

//在c裏面調用java實例的public屬性
JNIEXPORT jint JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_addNum
        (JNIEnv *env, jobject obj) {
    jclass jclazz = (*env)->GetObjectClass(env, obj);
    jfieldID fid = (*env)->GetFieldID(env, jclazz, "num", "I");
    jint num = (*env)->GetIntField(env, obj, fid);
    num++;
    return num;
}

//在c裏面調用java實例的static屬性
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticFiled
  (JNIEnv *env, jobject obj) {
        jclass jclazz = (*env)->GetObjectClass(env, obj);
        jfieldID fid = (*env)->GetStaticFieldID(env, jclazz, "staticField", "Ljava/lang/String;");
        jstring name = (jstring)(*env)->GetStaticObjectField(env, jclazz, fid);
        const char* str = (*env)->GetStringUTFChars(env, name, JNI_FALSE);
        char ch[30] = "C code, ";
        strcat(ch, str);
        jstring new_str = (*env)->NewStringUTF(env, ch);
        (*env)->SetStaticObjectField(env, jclazz, fid, new_str);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPrivateField
 * Signature: ()V
 */
 //在c裏面調用java實例的private屬性
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPrivateField
  (JNIEnv *env, jobject obj) {
        jclass clazz = (*env)->GetObjectClass(env, obj);
        jfieldID fid = (*env)->GetFieldID(env, clazz, "age", "I");
        jint age = (*env)->GetIntField(env, obj, fid);
        if (age > 18) {
            age = 18;
        } else {
            age--;
        }
        (*env)->SetIntField(env, obj, fid, age);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPublicMethod
 * Signature: ()V
 */
 //在c裏面調用java實例的public方法
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPublicMethod
  (JNIEnv *env, jobject obj) {
        jclass clazz = (*env)->GetObjectClass(env, obj);
        jmethodID mid = (*env)->GetMethodID(env, clazz, "testPublicMethod", "(Ljava/lang/String;)V");
        char c[10] = "I am C";
        jstring jc = (*env)->NewStringUTF(env, c);
        (*env)->CallVoidMethod(env, obj, mid, jc);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessStaticMethod
 * Signature: ()V
 */
 //在c裏面調用java實例的static方法
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticMethod
  (JNIEnv *env, jobject obj) {
        jclass clazz = (*env)->GetObjectClass(env, obj);
        jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "testStaticMethod", "()V");
        (*env)->CallStaticVoidMethod(env, clazz, mid);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessSuperMethod
 * Signature: ()Ljava/lang/String;
 */
 //在c裏面調用java實例的父類方法
JNIEXPORT jstring JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessSuperMethod
  (JNIEnv *env, jobject obj) {
        jclass jclazz = (*env)->FindClass(env, "aes/example/com/aesjnidemo/demo/SuperJni");
        if (NULL == jclazz) {
            char c[10] = "error";
            return (*env)->NewStringUTF(env, c);
        }
        jmethodID mid = (*env)->GetMethodID(env, jclazz, "hello", "(Ljava/lang/String;)Ljava/lang/String;");
        char ch[10] = "C call ";
        jstring jstr = (*env)->NewStringUTF(env, ch);
        return (jstring)(*env)->CallNonvirtualObjectMethod(env, obj, jclazz, mid, jstr);
  }

 

測試結果:函數

相關文章
相關標籤/搜索