1. 添加native接口
static{
System.loadLibrary("JniTest");
}
private native int Add(double num1,double num2);
private native int Sub(double num1,double num2);
private native int Mul(double num1,double num2);
private native int Div(double num1,double num2);
2.Build->Make Project
验证工程中并无其他错误,并对工程进行编译,生成.class文件
在Build/intermediates/classes/debug里面
3.javah 生成.h文件
在工程的app/src/main/java 目录下
cmd 执行 javah com.example.caculate.MainActivity 命令,就会生成.h文件
建立jni目录,将.h拷贝进去
4.jni目录下实现.c
新建一个.c 实现.h中的函数
5.Build->Make Project
会报错
在local.properties文件中增加ndk的路径
sdk.dir=C\:\\Users\\Alif\\AppData\\Local\\Android\\Sdk
ndk.dir=I\:\\Android\\android-ndk-r11c
在app下面的build.gradle里面增加 so的名称
\app\build.gradle
ndk {
moduleName "JniTest"
abiFilters "armeabi", "armeabi-v7a", "x86"
}
6.Build->Make Project 就可以编译出so文件了
生成的so在app/Build/intermediates/ndk/debug/lib下面
我们在jni目录下增加一个Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JniTest
LOCAL_SRC_FILES := main.c
include $(BUILD_SHARED_LIBRARY)
然后ndk-build 生成libs目录
将libs目录名称改为 jniLibs 就会自动打包到apk里面了
.h和.c文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_caculate_MainActivity */ #ifndef _Included_com_example_caculate_MainActivity #define _Included_com_example_caculate_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_caculate_MainActivity * Method: Add * Signature: (DD)I */ JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Add (JNIEnv *, jobject, jdouble, jdouble); /* * Class: com_example_caculate_MainActivity * Method: Sub * Signature: (DD)I */ JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Sub (JNIEnv *, jobject, jdouble, jdouble); /* * Class: com_example_caculate_MainActivity * Method: Mul * Signature: (DD)I */ JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Mul (JNIEnv *, jobject, jdouble, jdouble); /* * Class: com_example_caculate_MainActivity * Method: Div * Signature: (DD)I */ JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Div (JNIEnv *, jobject, jdouble, jdouble); #ifdef __cplusplus } #endif #endif #include <jni.h> #define jintJNICALL #ifndef _Included_com_example_caculate_MainActivity #define _Included_com_example_caculate_MainActivity #ifdef __cplusplus extern "C" { #endif JNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Add (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { return (jint)(num1 + num2); } JNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Sub (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { return (jint)(num1 - num2); } JNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Mul (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { return (jint)(num1 * num2); } JNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Div (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { if (num2 == 0) return 0; return (jint)(num1 / num2); } #ifdef __cplusplus } #endif #endif
使用动态注册JNI
1.函数名称太长,因为是javah生成的头文件,名称太长
2.每一个类都要javah一次,很麻烦
在jni目录下生成编写.c
#include <jni.h> #include <stdio.h> //#include <assert.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> JNIEXPORT jint JNICALL native_Add (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { return (jint)(num1 + num2 +1); } JNIEXPORT jint JNICALL native_Sub (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { return (jint)(num1 - num2 +1); } JNIEXPORT jint JNICALL native_Mul (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { return (jint)(num1 * num2 +1); } JNIEXPORT jint JNICALL native_Div (JNIEnv *env, jobject obj, jdouble num1, jdouble num2) { if (num2 == 0) return 0; return (jint)(num1 / num2 +1); } //Java和JNI函数的绑定表 static JNINativeMethod gMethods[] = { {"Add", "(DD)I", (void *)native_Add}, {"Sub", "(DD)I", (void *)native_Sub}, {"Mul", "(DD)I", (void *)native_Mul}, {"Div", "(DD)I", (void *)native_Div}, }; //注册native方法到java中 static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = (*env)->FindClass(env, className); if (clazz == NULL) { return JNI_FALSE; } if ((*env)->RegisterNatives(env, clazz, gMethods,numMethods) < 0){ return JNI_FALSE; } return JNI_TRUE; } int register_ndk_load(JNIEnv *env) { return registerNativeMethods(env, "com/example/caculate/MainActivity", gMethods,sizeof(gMethods) / sizeof(gMethods[0])); //NELEM(gMethods)); } JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { return result; } register_ndk_load(env); // 返回jni的版本 return JNI_VERSION_1_4; }
编写Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := JniTest_jni
LOCAL_SRC_FILES := MyJniCalc.c
LOCAL_SHARED_LIBRARIES := libandroid_runtime
include $(BUILD_SHARED_LIBRARY)
使用ndk-build生成so文件
还是移到jniLibs目录下
最后成功修改
78+11 +1 = 90
源码:http://pan.baidu.com/s/1kULyvDd 密码 m8ns