Android Studio NDK 開發之在Native中調用java層的函數

在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']) //多了這句
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章