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); }
測試結果:函數