前言
在上一篇《》的动态注册并调用Java方法,上次也说了可以把公共部分封装一下。
说干就干,今天就把上次代码封装一下。
正文
我这不介绍完整的动态注册,有需要可以看《》。这里只是个人流水账。
Hello.java
package com.biumall.dynamic.one; public class Hello { //1. load Hello.so static { System.loadLibrary("Hello"); } // 2. define native computer() public static native int computer(String type, int a, int b); //add public int add(int x, int y) { return x + y; } //sub public int sub(int x, int y) { return x - y; } }
JNI
把之前Hello.c的代码拆分为Log.h,JNICommon.h和Hello.c,也就是吧公共部分单独抽出,这样移植就方便多了。
Log.h
#include <android/log.h> //定义TAG日志打印 #define LOG_TAG "from_dynamic_jni_" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
网上有封装Log等级控制,方便控制日志打印,目前没空,后续补上。
JNICommon.h
就获取数组大小和本地方法注册。
#include <jni.h> //获取数组大小 #define ARRAY_LENGTH(x) ((int)(sizeof(x) / sizeof((x)[0]))) //注册本地方法 int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods,int methods_size) { jclass clazz = (*env)->FindClass(env, className); if (!clazz) { return JNI_ERR; } int result = (*env)->RegisterNatives(env, clazz, methods, methods_size); if (result < 0) { return JNI_ERR; } return JNI_OK; }
Hello.c
特意把每步单独隔开,方便初学者(我就是)查看。
#include "JNICommon.h" #include "Log.h" #include<string.h> /** * ---------------------------第一步 start --------------------------- * 定义Hello.java类路径[包名+类名,只不过.换成了/] * 包名+类名:com.biumall.dynamic.one.Hello */ #define DYNAMIC_CLASS "com/biumall/dynamic/one/Hello" /** * ---------------------------第一步 end --------------------------- */ /** * ---------------------------第二步 start --------------------------- * c_add()用于调用Java方法 * @param env env * @param jclazz jclazz * @param x x * @param y y * @return */ int c_add(JNIEnv *env, jclass jclazz, int x, int y) { jmethodID methodID = (*env)->GetMethodID(env, jclazz, "add", "(II)I"); jobject object = (*env)->AllocObject(env, jclazz); return (*env)->CallIntMethod(env, object, methodID, x, y); } /** * c_sub()用于调用Java方法 * @param env env * @param jclazz jclazz * @param x x * @param y y * @return */ int c_sub(JNIEnv *env, jclass jclazz, int x, int y) { jmethodID methodID = (*env)->GetMethodID(env, jclazz, "sub", "(II)I"); jobject object = (*env)->AllocObject(env, jclazz); return (*env)->CallIntMethod(env, object, methodID, x, y); } /** * 本地方法computer实现 */ JNIEXPORT jint JNICALL native_computer(JNIEnv *env, jclass jclazz, jstring type, jint a, jint b) { const char *charType = (*env)->GetStringUTFChars(env, type, 0); int count; if (!strcmp(charType, "-")) { count = c_sub(env, jclazz, a, b); } else if (!strcmp(charType, "+")) { count = c_add(env, jclazz, a, b); } (*env)->ReleaseStringUTFChars(env, type, charType); return count; } /** * ---------------------------第二步 end --------------------------- */ /** * ---------------------------第三步 start --------------------------- * 定义Java和JNI函数的绑定表 * 方法数组,分别为:(native方法 , 方法签名 , 函数指针[JNI中需要实现的方法名]) * 通过javac和javap 获取 方法签名 */ JNINativeMethod method_table[] = { {"computer", "(Ljava/lang/String;II)I", (void *) native_computer}, }; /** * ---------------------------第三步 end --------------------------- */ /** * ---------------------------第四步 start --------------------------- * JNI_OnLoad */ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved ){ JNIEnv *env = NULL; int result = (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6); LOGD("JNI_OnLoad 1 result : %d", result); if(result != JNI_OK){ return JNI_ERR; } result = registerNativeMethods(env, DYNAMIC_CLASS, method_table, ARRAY_LENGTH(method_table)); LOGD("JNI_OnLoad 2 result : %d", result); if(result != JNI_OK){ return JNI_ERR; } return JNI_VERSION_1_6; } /** * ---------------------------第四步 end --------------------------- */
参考文章
-
《》
历史上的今天
暂无评论...
随机推荐
AIDL个人理解总结
前言之前也简单的使用过Android的AIDL,但也都是局限于使用,至于启动的原理等都没去了解。记录一下个人对AIDL的理解,方便自己查阅。正文之前AIDL的简单Demo:《Android aidl简单使用》和《Android aidl简单使用2》。回归正题。AIDL是Android ...
视频播放中,拖动进度条可以seek到相应视频帧
前言项目中需求:拖动进度条时,或是在进度条上方或是在屏幕中间,显示拖动进度条位置时刻的某一帧画面下面是参考文章一中提到(摘抄于)下面我想到的4个方案:1、在拖动过程中,可以通过TextureView来显示预览图,拖动进度条到某个position后,通过textureView.getBi...
Handler内存泄漏之使用静态内部类并持有外部类的弱引用
非静态内部类或者匿名类持有外部类的引用,如果外部类正在销毁,内部类比如Handler还在延迟处理一些消息,那么其持有的外部类引用就无法销毁解决方法:使用静态内部类并持有外部类的弱引用package com.la.allwater;import android.app.Activity;i...
村上春树:请认真生活
您是属于喜欢说话的人呢,还是不太爱说话?我呢,应该算不爱说话的。虽然视情况看对手,有时会变得口若悬河,不过平常却是闷葫芦一个。也害怕详尽地说明什么,尽量不做这类事情。哪怕话说得不透彻,招致周围的误解(这种事屡屡发生),也照样坦然自若:没办法,人生就是这么回事。不是自吹,这方面我倒是做得很高明。...
git branch的使用记录
前言查看分支,切换分支等简单记录正文查看分支git branch -a查看当前的本地分支与远程分支的关联关系git branch -vv切换分支切换到xxx分支git checkout xxxx删除分支git branch -D xxx提交分支git push origi...
[转]android NTP时间同步
推荐使用 极客导航:极客导航(http://www.91es.com/jike.html)相关文件:frameworks/base/services/java/com/android/server/SystemServer.javaframeworks/base/services/j...