废话不多说!
<1> : 新建一个DurianAsJni的android工程.
<2> : 新建一个jni的java接口类:
package org.durian.durianasjni; /** * Project name : DurianAsJni * Created by zhibao.liu on 2016/3/28. * Time : 19:33 * Email [email protected] * Action : durian */ public class aslib { public native float getDurianLibVersion(); static{ System.loadLibrary("aslib"); } }
<3> : 然后在src目录下新建一个jni目录,在jni目录下添加Android.mk和Application.mk.
<4> : 由于这里使用的是onload的方式,所以新建jni_onload.h,jni_onload.cpp
jni_onload.h
#include<jni.h> #ifndef _ON_LOAD_HEADER_H__ #define _ON_LOAD_HEADER_H__ #ifdef __cplusplus extern "C" { #endif JNIEnv* getJNIEnv(); int jniThrowException(JNIEnv *env,const char* className,const char* msg); int jniRegisterNativeMethods(JNIEnv* env,const char* className,const JNINativeMethod* gMethod,int numMethods); #ifdef __cplusplus } #endif #endif
jni_onload.cpp
#include "jni_onload.h" #include "durian_opencv.h" extern int register_android_jni_durian_android(JNIEnv *env); /* extern int register_android_jni_durian_android_1(JNIEnv *env); ... extern int register_android_jni_durian_android_n(JNIEnv *env); */ static JavaVM *sEnv; int jniThrowException(JNIEnv *env, const char* className, const char* msg) { jclass exceptionClass = env->FindClass(className); if (exceptionClass == NULL) { return -1; } if (env->ThrowNew(exceptionClass, msg) != JNI_OK) { } return 0; } JNIEnv* getJNIEnv() { JNIEnv* env = NULL; if (sEnv->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return NULL; } return env; } int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return -1; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return -1; } return 0; } jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = JNI_ERR; sEnv = vm; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return result; } LOGI("JNI_OnLoad..."); /*ready to register all methods */ if (register_android_jni_durian_android(env) != JNI_OK) { goto end; } //following could do it as the previous the way of register /*if (register_android_jni_durian_android_1(env) != JNI_OK) { goto end; } ... if (register_android_jni_durian_android_n(env) != JNI_OK) { goto end; }*/ return JNI_VERSION_1_4; end: return result; }
这两个文件都被我弄成标配文件了.
<5> : 功能源代码,在jni目录下新建durian_opencv.h和durian_opencv.cpp,代码如下:
durian_opencv.h
// // Created by $zhibao.liu on 2016/3/28. // #ifndef DURIANASJNI_DURIAN_OPENCV_H #define DURIANASJNI_DURIAN_OPENCV_H #include<string.h> #include<stdlib.h> #include <android/log.h> #include "jni_onload.h" #define LOG_TAG "durian" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) #endif //DURIANASJNI_DURIAN_OPENCV_H
对应的durian_opencv.cpp
// // Created by $zhibao.liu on 2016/3/28. // #include "durian_opencv.h" const static char *classpath="org/durian/durianasjni/aslib"; namespace android{ float getDurianLibVersion(JNIEnv *env, jobject thiz){ return 0.5; } } using namespace android; static JNINativeMethod mMethods[] = { { "getDurianLibVersion", "()F",(void *) getDurianLibVersion }, }; int register_android_jni_durian_android(JNIEnv* env) { return jniRegisterNativeMethods(env, classpath, mMethods,sizeof(mMethods) / sizeof(mMethods[0])); }
写完c源代码后,修改Android.mk文件:
LOCAL_PATH $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := aslib LOCAL_SRC_INCLUDE=jni_onload.cpp durian_opencv.cpp LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)
<6> : NDK环境配置:
gradle.properties文件最后一行添加:
android.useDeprecatedNdk=true
local.properties文件最后一行添加NDK包的路径:
ndk.dir=D\:\\liuzhibao\\Android\\android-ndk-r10
最后再build.gradle文件中添加ndk编译:
ndk{ moduleName "aslib" ldLibs "log", "z", "m" abiFilters "armeabi", "armeabi-v7a", "x86" }
就差不多了
<7> : 在android java主程序中添加测试程序:
package org.durian.durianasjni; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private aslib mlib; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mlib=new aslib(); float ver=mlib.getDurianLibVersion(); Toast.makeText(MainActivity.this,"lib version : "+ver,Toast.LENGTH_SHORT).show(); } }