Android JNI的动态注册
来源:互联网 发布:网络用语猜成语 编辑:程序博客网 时间:2024/05/18 19:20
我们知道Androd 使用JNI的注册方法包括两个,静态注册和动态注册。
静态注册就是通过javah命令生成.h文件,然后实现声明的函数即可,但此类函数的函数名都比较长:Java+包名+类名+方法名。而动态注册则没有这一限制。先以下面这个例子进行说明,例子中的jni函数参考了Android M源码。
- 我们新建一个的Android工程,包含一个默认的MainActivity。代码如下:
package com.example.jnidynamic;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;public class MainActivity extends Activity { private TextView mTextView; // 声明一个jni函数,待会去实现 private native String getStringFromJni(); static { System.loadLibrary("myJNI"); // 加载库,待会会用NDK去生成该库 } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView)findViewById(R.id.my_text_view); mTextView.setText(getStringFromJni()); // 原理很简单,显示一个从JNI层返回的字符串 }}
- 右键工程, Android tools -> Add native …,库的名字填写上面的myJNI即可。eclipse要先配置好NDK,这里不再说明。其实也可以不用在eclipse配置NDK,自己用NDK命令去编译也可以。
myJNI.cpp
#include <jni.h>#include <android/log.h>#include <string.h>#include <stdio.h>#include <jni.h>#include <assert.h>/* 定义了一些宏,这里用来输出Log用的,JNI层输出Android LOG, JNI层输出LOG可以参考我以前写的,LOG_TAG是tag */#ifndef LOG #define LOG_TAG "myJNI"#define ALOGD(...) \ __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__);#define ALOGE(...) \ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);#define ALOGV(...) \ __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__);#endif LOG#ifndef NELEM# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))#endif// c函数jstring native_hello(JNIEnv* env, jobject thiz){ return env ->NewStringUTF("hello world from jni~");}// java类的位置static const char *classPathName = "com/example/jnidynamic/MainActivity";// 映射表,这里将我们java函数和c函数对应起来static JNINativeMethod gMethods[] = { {"getStringFromJni", "()Ljava/lang/String;", (void*)native_hello},};/* 下面的可以说,基本上是模板了,以后直接copy就行 */static int jniRegisterNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods){ jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { ALOGE("Native registration unable to find class '%s'", className); return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { ALOGE("RegisterNatives failed for '%s'", className); return JNI_FALSE; } return JNI_TRUE;}static int register_my_jni_methods(JNIEnv* env) { return jniRegisterNativeMethods(env, classPathName, gMethods, NELEM(gMethods));}// 在我们load该so库的时候,JNI_OnLoad将会自动被调用,来注册JNI函数jint JNI_OnLoad(JavaVM* vm, void*){ JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { ALOGE("ERROR: GetEnv failed\n"); goto bail; } assert(env != NULL); if (register_my_jni_methods(env) < 0) { ALOGE("ERROR: native registration failed\n"); goto bail; } /* success -- return valid version number */ ALOGE("SUCCESS: native registration successed\n"); result = JNI_VERSION_1_4;bail: return result;}
Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llogLOCAL_MODULE := myJNILOCAL_SRC_FILES := myJNI.cppinclude $(BUILD_SHARED_LIBRARY)
其实这里的重点是JNINativeMethod这里结构体
typedef struct { const char* name; //Java中函数的名字 const char* signature; //用字符串描述的函数的参数和返回值 void* fnPtr; //指向C函数的函数指针} JNINativeMethod;
这里面我觉得比较难书写的是signature, 反映的是函数的参数和返回值。括号内()为参数,最后为返回值。
具体的每一个字符的对应关系如下
上面的都是基本类型。如果Java函数的参数是java的某个类,则以”L”开头,以”;”结尾,中间是用”/” 隔开的包名和类名。而其对应的C函数名的参数则统一为jobject。但String类是个例外,其对应的类为jstring。
举下面几个例子:
如果java类是一个内部类的话,则用$作为类名间的分隔符。
例如 :
“(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z”
0 0
- Android JNI的动态注册
- Android 动态注册JNI
- Android: JNI动态注册
- Android JNI动态注册
- Android 动态注册JNI
- Android JNI 使用的数据结构JNINativeMethod详解 动态注册JNI
- android 动态注册Jni函数
- Android 动态注册JNI函数
- Android 动态注册JNI函数
- Android jni 静态注册 和动态注册
- Android Studio3.0开发JNI流程------JNI静态注册和动态注册(多个类的native动态注册-经典篇)
- JNI函数的动态注册
- Android JNI使用方法(“动态注册”)
- Android JNI使用方法(“动态注册”)
- [Android]JNI动态注册Java函数教程
- android NDK开发 静态/动态注册 jni
- Android JNI 动态注册方法(JNI_OnLoad)
- Android Studio jni动态注册步骤
- Hadoop/spark安装实战(系列篇2)安装虚拟机、PieTTY、winscp、JDK、配置DNS、SSH免密码登录
- 串口调试助手--VC++ 2010 开发
- Perl 实现简单的html 标签筛选
- 1101. Quick Sort (25)
- 0912_Collective Intelligence Programming Reading Notes
- Android JNI的动态注册
- 测试你是否和LTC水平一样高 1407 (简单数学题)
- posix线程栈
- 判断浏览器是否安装pdf插件
- 改革70周年
- IOS 调用系统键盘 设置搜索字段和事件
- MATLAB中find函数用法
- 超轻量级的安卓SlidingMenu库
- HDU1231 最大连续子序列