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); }
测试结果:函数