Android NDK 开发
来源:互联网 发布:大数据安全标准化 编辑:程序博客网 时间:2024/06/07 18:49
Android NDK 开发
JNI 基础
- Java 与 C/C++ 基本类型对应
定义在
JDK_HOME/include/jni.h
JDK_HOME/include/platform/jni_md.h
- 引用类型对应
域和方法IDs
jfiledID,jmethodIDstruct _jfieldID; /* opaque structure */ typedef struct _jfieldID *jfieldID; /* field IDs */ struct _jmethodID; /* opaque structure */ typedef struct _jmethodID *jmethodID; /* method IDs */
jvalue Type
typedef union jvalue { jboolean z; jbyte b; jchar c; jshort s; jint i; jlong j; jfloat f; jdouble d; jobject l; } jvalue;
- 类型签名(Type Signatures)
对于Java方法:
long f (int n,String s,int[] arr);
有如下签名:
(ILjava/lang/String;[I)J
需要注意的是引用类型String,必须像这样Ljava/lang/String; 分号不能少。
参考
JNI 几个重要函数及变量
System.loadLibrary()
导入so库函数。比如你的库是libhelljni.so 那么导入是这样的System.loadLibrary(“helljni”)
该函数调用一般是在静态代码块中static{ System.loadLibrary("helljni");}
JNIEnv
JNIEnv JNI接口指针 用于调用方法等JNI_OnLoad
在加载so之后需要做的工作,主动注入native函数需要实现
JNI 主动注册和被动注册 native 函数
调用 RegisterNatives 主动注册JNI函数
Android 系统模块一般都用这个方法。具体可查看源码
frameworks\base\core\jni
frameworks\base\services\jni
fremeworks\base\media\jni我们来拿源码Media部分代码看看这个这过程这么做的。
首先,需要在Java代码中声明native函数
framework/base/media/java/android/media/MediaScannerpackage android.media;.......public class MediaScanner{ static { System.loadLibrary("media_jni"); native_init(); } ......... private static native final void native_init(); private native final void native_setup(); private native final void native_finalize();}
C++实现/framework/base/media/jni/android_media_MediaScanner.cpp
// This function gets a field ID, which in turn causes class initialization.// It is called from a static block in MediaScanner, which won't run until the// first time an instance of this class is used.static void android_media_MediaScanner_native_init(JNIEnv *env){ ALOGV("native_init"); jclass clazz = env->FindClass(kClassMediaScanner); if (clazz == NULL) { return; } fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); if (fields.context == NULL) { return; }}.......static JNINativeMethod gMethods[] = {......{ "native_init", "()V", (void *)android_media_MediaScanner_native_init},{ "native_setup", "()V", (void *)android_media_MediaScanner_native_setup},{ "native_finalize", "()V", (void *)android_media_MediaScanner_native_finalize},};........// This function only registers the native methods, and is called from// JNI_OnLoad in android_media_MediaPlayer.cppint register_android_media_MediaScanner(JNIEnv *env){ return AndroidRuntime::registerNativeMethods(env, kClassMediaScanner, gMethods, NELEM(gMethods));}
真正导入so然后调用JNI_OnLoad 然后注册registerNativeMethods否则找不到native函数
我们看看framework/base/media/jni/android_media_MediaPlayer.cpp......extern int register_android_media_MediaScanner(JNIEnv *env);......jint JNI_OnLoad(JavaVM* vm, void* reserved){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_android_media_MediaScanner(env) < 0) { ALOGE("ERROR: MediaScanner native registration failed\n"); goto bail;}......./* success -- return valid version number */result = JNI_VERSION_1_4;bail: return result;}
被动注册Native函数
这个很多jni编写教程都是这种方法,大致流程是这样的
- 编写Java native 代码,javac 生产class(Android Studio 可以自动构建)
- 使用javah命令,生产包含JNI本地函数原型的头文件
一般生产的函数原型头文件是这样的
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_XXX_XXXX_utils_NativeSpeedTest */ #ifndef _Included_com_XXX_XXXX_utils_NativeSpeedTest #define _Included_com_XXX_XXXX_utils_NativeSpeedTest #ifdef __cplusplus extern "C" { #endif /* * Class: com_XXX_XXXX_utils_NativeSpeedTest * Method: startDownloadWireless * Signature: ([Ljava/lang/String;II)I */ JNIEXPORT jint JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_startDownloadWireless (JNIEnv *env, jclass cclass, jobjectArray jurls, jint jconns , jint jduration); /* * Class: com_XXX_XXXX_utils_NativeSpeedTest * Method: signatureVerify * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_signatureVerify (JNIEnv *env, jclass cclass, jstring jstr); /* * Class: com_XXX_XXXX_utils_NativeSpeedTest * Method: init * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_init (JNIEnv *env, jclass cclass, jstring jstr); /* * Class: com_XXX_XXXX_utils_NativeSpeedTest * Method: uninit * Signature: ()V */ JNIEXPORT void JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_uninit (JNIEnv *env, jclass cclass); /* * Class: com_XXX_XXXX_utils_NativeSpeedTest * Method: startDownload * Signature: ([Ljava/lang/String;II)I */ JNIEXPORT jint JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_startDownload (JNIEnv *env, jclass cclass, jobjectArray jurls, jint jconns, jint jduration); /* * Class: com_XXX_XXXX_utils_NativeSpeedTest * Method: statUpload * Signature: ([Ljava/lang/String;II)I */ JNIEXPORT jint JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_statUpload (JNIEnv *env, jclass cclass, jobjectArray jurls, jint jconns, jint jduration); /* * Class: com_XXX_XXXX_utils_NativeSpeedTest * Method: callBack * Signature: (Ljava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_callBack (JNIEnv *env, jclass thiz, jstring jclassname, jstring jmethodname); #ifdef __cplusplus } #endif#endif
自动生产的话是没有定义变量像这样
/*
* Class: com_XXX_XXXX_utils_NativeSpeedTest
* Method: callBack
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_XXX_XXXX_utils_NativeSpeedTest_callBack
(JNIEnv , jclass, jstring, jstring);
自己加上变量名- 实现JNI本地函数
然后新建.cpp文件实现上面函数 生产C 共享库
ndk-build 生产so文件,Android studio 需要做ndk配置。
build.gradleandroid{ defaultConfig{ ndk{ moduleName "XXX" ldLibs "log" abiFilters "armeabi", "armeabi-v7a", "x86" } }}
在main/下建立 jni和jniLibs
gradle.properties加入
android.useDeprecatedNdk=true
- 通过JNI,调用JNI本地函数
这两种方式建议用主动注册方式(或者动态注册),编写起来函数名简便,且不需要VM去查找函数省时间。
参考
- Android NDK开发配置NDK
- Android NDK : NDK开发概要
- android NDK开发相关
- Android NDK应用开发
- Android NDK开发学习
- android NDK 开发
- Android NDK 开发
- android之NDK开发
- ANDROID 底层 NDK 开发
- android NDK 开发
- Android之NDK开发
- Android ndk开发入门
- Android ndk 开发demo
- Android NDK 开发分享
- Android NDK开发
- Android之NDK开发
- android NDK开发网站
- Android之NDK开发
- 加减密签名
- http
- DFS 与BFS优先搜索
- [LibreOJ β Round]ZQC的课堂
- DAY 21生成器、三元表达式、列表生成式、生成器表达式
- Android NDK 开发
- java HashMap底层数据结构
- java基础
- 第八章 IO库学习笔记(第一遍阅读)
- python 元组、字典
- 神经网络学习之单层感知器
- hibernate笔记-016-树状结构
- linux网络编程之端口分类调研
- PAT练习-数素数