新建一个工程
在main下创建一个jni文件夹
Application.mk文件内容(写你要编译成那些版本的so文件)
APP_ABI := armeabi-v7a x86
Android.mk文件内容
1 //向编译系统描述 我要编译的文件在什么位置 要生成的文件叫什么名字, 是什么类型 2 LOCAL_PATH := $(call my-dir) 3 //清除上次编译的信息 4 include $(CLEAR_VARS) 5 LOCAL_CFLAGS+=-pie -fPIE 6 LOCAL_LDFLAGS+=-pie -fPIE 7 //在这里指定最后生成的文件的名字 8 LOCAL_MODULE := hello 9 //要编译的C的代码的文件名 10 LOCAL_SRC_FILES := hello.c 11 //编译后的指令集 ARM指令 12 LOCAL_ARM_MODE := arm 13 //依赖库 14 LOCAL_LDLIBS += -llog 15 //要生成的是一个动态链接库 16 include $(BUILD_SHARED_LIBRARY)
java层 代码
生成.h头文件(一定要在src/main/java目录下)
javah -jni -encoding UTF-8 com.qiaorui.jnidemo01.JNI
这下面是生成的.h文件的内容,把这些内容复制到.c文件
c代码
1 #include <jni.h> 2 #include<stdlib.h> 3 #include <android/log.h> 4 #define LOG_TAG "System.out" 5 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 6 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 7 8 JNIEXPORT jint JNICALL Java_com_qiaorui_jnidemo01_JNI_add 9 (JNIEnv* env, jobject thiz, jint x, jint y){ 10 return x+y; 11 } 12 13 14 JNIEXPORT jstring JNICALL Java_com_qiaorui_jnidemo01_JNI_sayHelloInC 15 (JNIEnv* env, jobject thiz, jstring jstr){ 16 //把java的字符串转换成c的字符串 17 char* cstr = (*env)->GetStringUTFChars(env,jstr,NULL); 18 //获取c字符串长度 19 int length = strlen(cstr); 20 int i; 21 //for循环执行完 cstr每一个元素都+1了 22 for(i=0;i<length;i++){ 23 *(cstr+i)+=1; 24 } 25 return (*env)->NewStringUTF(env,cstr); 26 27 } 28 29 30 31 JNIEXPORT jintArray JNICALL Java_com_qiaorui_jnidemo01_JNI_arrElementsIncrease 32 (JNIEnv* env, jobject thiz, jintArray jarr){ 33 //获取数组的长度 34 int length = (*env)->GetArrayLength(env,jarr); 35 //打印长度 36 LOGD("length=%d",length); 37 //获取数组首地址 38 //jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); 39 //jboolean java的boolean类型在C中的表示 40 //这个参数 在有些虚拟机中 用来作为 执行完GetIntArrayElements之后 是否创建了数组的副本的标志 41 //如果创建了副本 就会返回 true 1 42 //如果没创建副本返回false 0 Android中 这个参数不必使用 直接传NULL 没有意义的地址 43 jboolean isCopy = NULL; 44 int* p = (*env)->GetIntArrayElements(env,jarr,NULL); 45 46 int i ; 47 for(i = 0;i<length;i++){ 48 *(p+i)+=10; 49 } 50 //由于获取到了数组的首地址 所以通过指针操作了每一个元素之后 jarr里的每一个元素已经被修改了 51 //所以没有必要创建新的数组 直接把jarr作为返回值返回去 52 return jarr; 53 }
在jni目录下输入ndk-build编译
生成的so库
在App文件夹下的build.gradle文件里,找到defaultConfig项,在其项里添加如下代码(必须,否则会导致LoadLibrary时加载失败):
运行测试