Android Studio NDK 开发之在Native中调用java层的函数

本文介绍了如何在Android Studio的NDK环境中,从Native代码调用Java层的函数。主要讨论了在JNI_OnLoad()函数中进行调用的方法,并提及使用LOGI宏定义简化日志输出的过程。

在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']) //多了这句
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有你就有时间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值