Android JNI开发解析
2019-05-07 12:26
92 查看
1.JNI简介
JNI的含义:Java native interface,是为了方便Java调用C、C++本地代码所封装的一层接口
2.JavaVM和JNIEnv
JNI定义了两个关键数据结构,“JavaVM”和“JNIEnv”。这两者基本上都是指向函数表指针的指针。(在C ++版本中,它们是带有指向函数表的指针的类,以及用于指向表中的每个JNI函数的成员函数。)
JavaVM提供“调用接口”函数,允许您创建和销毁JavaVM的。理论上,每个进程可以有多个JavaVM,但Android只允许一个。
JNIEnv提供了大多数JNI功能。本地函数都接收JNIEnv作为第一个参数。
3.jclass,jmethodID和jfieldID
如果要从本机代码访问对象的字段,请执行以下操作:
- 获取类的类对象引用 FindClass
- 获取该字段的字段ID GetFieldID
- 使用适当的内容获取字段的内容,例如 GetIntField
4.JNI的注册方式
JVM 查找 4000 native 方法有两种方式:
- 按照 JNI 规范的命名规则(静态注册)
- 调用 JNI 提供的 RegisterNatives 函数,将本地函数注册到 JVM 中(动态注册)
4.1静态注册实现:
com_ad_jnidemo_JniUtils.h代码如下:
#ifndef _Included_com_ad_jnidemo_JniUtils #define _Included_com_ad_jnidemo_JniUtils #ifdef __cplusplus extern "C" { #endif /* * Class: com_ad_jnidemo_JniUtils * Method: getJniString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_ad_jnidemo_JniUtils_getJniString (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
注意:以上的com_ad_jnidemo_JniUtils.h文件是根据执行命令javah com.ad.jnidemo.JniUtils .java所生成的文件。
com_ad_jnidemo_JniUtils.cpp代码如下:
#include "com_ad_jnidemo_JniUtils.h" JNIEXPORT jstring JNICALL Java_com_ad_jnidemo_JniUtils_getJniString (JNIEnv *env, jclass) { // new 一个字符串,返回Hello World return env -> NewStringUTF("Hello World From Jni"); }
Java调用实现, JniUtils.java代码如下:
public class JniUtils { static { System.loadLibrary("JNIUtils"); } //native接口,将调用com_ad_jnidemo_JniUtils.cpp中的Java_com_ad_jnidemo_JniUtils_getJniString()方法 //静态注册 public static native String getJniString(); }
4.2动态注册实现:
com_ad_jnidemo_JniUtils.h代码不变,跟上面静态注册代码一样;
com_ad_jnidemo_JniUtils.cpp代码如下:
#include <assert.h> #include "com_ad_jnidemo_JniUtils.h" /////////////////////////////////////////////////////////////////////// /* * Static register */ JNIEXPORT jstring JNICALL Java_com_ad_jnidemo_JniUtils_getJniString (JNIEnv *env, jclass) { // new 一个字符串,返回Hello World return env -> NewStringUTF("Hello World From Static Reg Jni"); } /////////////////////////////////////////////////////////////////////// /* * Dynamic register */ //步骤一:定义需要注册的java文件 #define JNIREG_CLASS "com/ad/jnidemo/JniUtils" //步骤二:编写C++层的实现函数 jstring dynamic_reg_getJniString(JNIEnv* env, jobject thiz){ return env -> NewStringUTF("Hello World From Dynamic Reg Jni"); } //步骤三:方法对应表 //"getJniStringFromDynamicReg",注册java文件"com/ad/jnidemo/JniUtils"中的接口 //dynamic_reg_getJniString,C++层的实现函数 static JNINativeMethod gMethods[] = { {"getJniStringFromDynamicReg", "()Ljava/lang/String;", (void *) dynamic_reg_getJniString}, }; //步骤四:为某一个类注册本地方法,主要注册"com/ad/jnidemo/JniUtils"文件 static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = (env)->FindClass( className); if (clazz == NULL) { return JNI_FALSE; } if ((env)->RegisterNatives(clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } //同步骤四,为所有类注册本地方法 static int registerNatives(JNIEnv* env) { return registerNativeMethods(env, JNIREG_CLASS, gMethods,sizeof(gMethods) / sizeof(gMethods[0])); } //步骤五:执行动态注册 /* * System.loadLibrary("lib")时调用 * 如果成功返回JNI版本, 失败返回-1 */ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (( vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)) { return -1; } assert(env != NULL); if (!registerNatives(env)) {//注册 return -1; } result = JNI_VERSION_1_6; return result; }
实现关键步骤,请参照代码注释中的步骤一、二、三、四、五。
Java调用实现, JniUtils.java代码如下:
package com.ad.jnidemo; public class JniUtils { static { System.loadLibrary("JNIUtils"); } //native接口,将调用com_ad_jnidemo_JniUtils.cpp中的Java_com_ad_jnidemo_JniUtils_getJniString()方法 //静态注册 public static native String getJniString(); //动态注册接口 public static native String getJniStringFromDynamicReg(); }
4.3 mk编译文件
Android.mk文件如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := JNIUtils LOCAL_SRC_FILES := com_ad_jnidemo_JniUtils.cpp include $(BUILD_SHARED_LIBRARY)
Application.mk文件如下:
APP_MODULES := JNIUtils APP_ABI := all APP_STL = c++_static
相关文章推荐
- Android开发之JNI(一)--HelloWorld及遇到的错误解析
- jni开发之 Android.mk文件解析
- 【Android 系统开发】Android JNI 之 JNIEnv 解析
- 【Android 系统开发】Android JNI 之 JNIEnv 解析
- 【Android 系统开发】Android JNI/NDK (三) 之 JNIEnv 解析
- Android开发之JNI(一)--HelloWorld及遇到的错误解析
- 【Android 系统开发】Android JNI 之 JNIEnv 解析
- 【Android 系统开发】Android JNI 之 JNIEnv 解析
- android开发中遇到的2个路径问题和html解析问题
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- 解决android某些应用开发某些类无法解析/找到的问题--使用android隐藏类的方法
- Android 开发中用到的几个多线程解析
- Android JNI开发提高篇
- android 条码识别软件开发全解析
- 总结:Android JNI开发疑点
- Android网络开发中如何使用JSON进行网络通信---Android JSON数据通讯方法解析
- Android JNI开发入门之二
- Android-NDK开发之基础--Android JNI有关Java类命名方式
- Android网络开发中如何使用JSON进行网络通信---Android JSON数据通讯方法解析