在Native中调用java层的函数
Java层
JniHandler.java
1.调用私有函数输出信息
@Keep
private void updateStatus(String msg) {
if (msg.toLowerCase().contains("error")) {
Log.e("JniHandler", "Native Err: " + msg);
} else {
Log.i("JniHandler", "Native Msg: " + msg);
}
}
2.获取当前android系统的版本
@Keep
static public String getBuildVersion() {
return Build.VERSION.RELEASE;
}
3.获取android系统运行时闲置的内存空间大小
@Keep
public long getRuntimeMemorySize() {
return Runtime.getRuntime().freeMemory();
}
Native层
由于只是调用这些函数来获取相应的信息因此可以都在
JNI_OnLoad()函数中获取并调用
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
//将结构体所在内存的每个字节的内容设置为0;
memset(&g_ctx, 0, sizeof(g_ctx));
//为结构体的javaVm赋值
g_ctx.javaVM = vm;
//拿到该线程的JNIEnv*结构体存入env中
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
//////////////
jclass clz=(*env)->FindClass(env,
"com/wbl/ndktest/JniHandler");
//引用这个JniHandler类
g_ctx.jniHelperClz=(*env)->NewGlobalRef(env,clz);
//查找init的方法
jmethodID jniHelperCtor=(*env)->GetMethodID(env,g_ctx.jniHelperClz,"<init>","()V");
//新建一个jniHandler对象
jobject handler=(*env)->NewObject(env,g_ctx.jniHelperClz,jniHelperCtor);
//引用这个对象
g_ctx.jniHelperObj=(*env)->NewGlobalRef(env,handler);
//找到updateStatus方法.
jmethodID updateStatus=(*env)->GetMethodID(env,g_ctx.jniHelperClz,"updateStatus","(Ljava/lang/String;)V");
sendJavaMsg(env,g_ctx.jniHelperObj,updateStatus,"Hello EveryOne");
queryRuntimeInfo(env,g_ctx.jniHelperObj);
return JNI_VERSION_1_6;
}
//调用updateStatus方法 发送一个消息
void sendJavaMsg(JNIEnv *env,jobject instance,
jmethodID func,const char* msg){
//获得一个jstring的对象
jstring javaMsg=(*env)->NewStringUTF(env,msg);
//调用updateStatus方法,将jstring作为参数传入
(*env)->CallVoidMethod(env,instance,func,javaMsg);
//删除javaMsg的引用
(*env)->DeleteLocalRef(env,javaMsg);
}
//调用java层的getBuildVersion()函数来获取Android系统的版本
//调用java层的getRuntimeMemorySize()函数来获取当前系统运行时内存闲置的空间大小
JNIEXPORT void queryRuntimeInfo(JNIEnv *pInterface, jobject pVoid) {
//查找到getBuildVersion()方法
jmethodID versionFunc=(*pInterface)->GetStaticMethodID(pInterface,g_ctx.jniHelperClz,
"getBuildVersion","()Ljava/lang/String;");
//调用方法获取到版本号
jstring buildVersion=(*pInterface)->CallStaticObjectMethod(pInterface,g_ctx.jniHelperClz,
versionFunc);
//将jstring的字符串转换为char*类型的字符串
const char *version=(*pInterface)->GetStringUTFChars(pInterface,buildVersion,NULL);
//在log中输出版本信息
LOGI("version %s",version);
//释放jstring类型的变量
(*pInterface)->ReleaseStringUTFChars(pInterface,buildVersion,version);
//删除本地引用
(*pInterface)->DeleteLocalRef(pInterface,buildVersion);
//查找getRuntimeMemorySize()函数
jmethodID memFunc=(*pInterface)->GetMethodID(pInterface,g_ctx.jniHelperClz,"getRuntimeMemorySize","()J");
//调用该函数获取内存闲置空间大小
jlong result=(*pInterface)->CallLongMethod(pInterface,pVoid,memFunc);
//输出内存闲置空间大小
LOGI("Runtime free memory size: %lld", result);
(void)result;
}
在代码中出现了一个LOGI函数 这是宏定义的一个函数用于简化在android中输入log信息的参数设置
//需要先引入头文件
#include <android/log.h>
//设置宏定义
#define LOGI(...) \
((void)__android_log_print(ANDROID_LOG_INFO, kTAG, __VA_ARGS__))
还需要在 module:app的build.gradle的ndk标签中加入库的引用
ndk{
moduleName='wbl-jni'
toolchain= 'clang'
CFlags.addAll(['-Wall'])
ldLibs.addAll(['android','log']) //多了这句
}
本文介绍了如何在Android Studio的NDK环境中,从Native代码调用Java层的函数。主要讨论了在JNI_OnLoad()函数中进行调用的方法,并提及使用LOGI宏定义简化日志输出的过程。
842

被折叠的 条评论
为什么被折叠?



