Android Studio JNI編程以及NDK環境配置

1. 新建一個工程,並添加JNI文件夾。



2. 在生成的jni文件夾中添加cpp文件。





3. 在添加的cpp文件添加代碼。這裏我們採用動態註冊的方式來添加jni函數,比較方便,不需要用javah生成.h文件

#include <jni.h>
#include <android/log.h>
#include <assert.h>
#include <stdio.h>
/* 輸出Log的宏 */
#ifndef LOG
#define LOG_TAG "imgprocess"
#define ALOGD(...) \
            __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__);
#define ALOGE(...) \
            __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);
#define ALOGV(...) \
            __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__);
#endif LOG
#ifndef NELEM
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
#endif
jstring native_hello(JNIEnv* env, jobject thiz)
{
    return env ->NewStringUTF("hello world from jni~");
}
//native函數所在java類的位置
static const char *classPathName = "com/test/hc/MainActivity";
// 映射表,這裏將我們java函數和c函數對應起來
static JNINativeMethod gMethods[] = {
        {"native_hello", "()Ljava/lang/String;", (void*)native_hello},
};
int registerNativeMethods(JNIEnv* env, const char* className,
                                    JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        ALOGE("Native registration unable to find class '%s'", className);
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        ALOGE("RegisterNatives failed for '%s'", className);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
//static
int register_my_jni_methods(JNIEnv* env)
{
    return registerNativeMethods(env, classPathName, gMethods, NELEM(gMethods));
}
// 在我們load該so庫的時候,JNI_OnLoad將會自動被調用,來註冊JNI函數
jint JNI_OnLoad(JavaVM* vm, void*)
{
    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_my_jni_methods(env) < 0) {
        ALOGE("ERROR: native registration failed\n");
        goto bail;
    }
    ALOGE("SUCCESS: native registration successed\n");
    result = JNI_VERSION_1_4;
    bail:
    return result;
}



4. 在app的build.properties如下位置,添加ndk編譯項


moduleName:生成so庫的名字
ldLibs:鏈接時使用的庫,由於我們要打印log,所以需要引用
abiFilters:生成哪些abi體系架構的so庫



5. gradle.properties中添加android.useDeprecatedNdk=true

不然會出現如下錯誤:

Error:(14, 0) Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin.  For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.


6. 在local.properties中配置ndk路徑



7. 在MainActivity載入so庫,並聲明native函數




8. 運行的時候發現NDK報錯,這是NDK在windows下的一個bug,當僅僅編譯一個文件的時候就會出現此問題,解決辦法是再往jni文件夾加入一個空的cpp文件即可,ndk生成的so文件在app/build/intermediates/ndk/debug/lib目錄下,會自動打包到apk中:


最後運行結果如圖:





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章