NDK10_NDK开发流程、JNI线程

NDK开发汇总

一 NDK开发流程

使用so库和头文件开发

gradle指定开发平台,在defaultConfig目录里面
ndk {
abiFilters “armeabi”,“x86”
}
引入第三方库,在app.gralde中的android目录下
sourceSets.main {
jniLibs.srcDirs = [‘libs’]
jni.srcDirs = []
}

C++中找不到外部函数,需要在头文件前加extern “C” {}

二 JNI线程(从下往上看)

  • 实现<jni.h>声明的JNI_OnLoad方法
  • 调用registerNatives_Main注册Activity中定义的方法:native_newThead、native_setJniEnv
  • native_newThead创建多个线程
  • thread_fun
#include <jni.h>
#include <android/log.h>
#include <assert.h>
//#include <stddef.h>
#include <malloc.h>
#include <pthread.h>

//int __android_log_print(int prio, const char* tag, const char* fmt, ...)
#define TAG "Tim_JNI"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))

JavaVM* g_jvm = NULL;
jobject g_obj = NULL;

/*
 * Class:     com_dn_tim_dn_lsn_9_FileUtils
 * Method:    diff
 * Signature: (Ljava/lang/String;Ljava/lang/String;I)V
 */

//int addTest(int a, int b) {
//    LOGI("这是第三方so库调用测试  %d,%d",a,b);
//    return a+b;
//}



void* thread_fun(void * arg) {

    JNIEnv  *env;
    jclass cls;
    jmethodID mid,mid1;

    if ( (*g_jvm) -> AttachCurrentThread(g_jvm, &env, NULL) != JNI_OK ) {
        LOGI("%s AttachCurrentThread error failed ",__FUNCTION__);
        return NULL;
    }

    cls = (*env) -> GetObjectClass(env ,g_obj);
    if (cls == NULL) {
        LOGI("findClass error....");
        goto  error;
    }
    LOGI("call back begin");
    mid = (*env) -> GetStaticMethodID(env, cls, "formJni", "(I)V");
    if (mid == NULL) {
        LOGI("GetStaticMethodID error....");
        goto  error;
    }

    (*env) -> CallStaticVoidMethod(env, cls, mid, (int)arg);

    mid1 = (*env) -> GetMethodID(env, cls, "form_JNI_Again", "(I)V");
    if (mid1 == NULL) {
        LOGI("GetMethodID error....");
        goto  error;
    }
    (*env) ->CallVoidMethod(env, g_obj, mid1 ,(int)arg);

    error:
    if ((*g_jvm) -> DetachCurrentThread(g_jvm) != JNI_OK) {
        LOGI("%s DetachCurrentThread error failed ",__FUNCTION__);
    }
    pthread_exit(0);
}




JNIEXPORT void JNICALL native_newThead
        (JNIEnv *env, jclass clazz)
{
    LOGI("newThread begin");
    int i;
    pthread_t pt[5];

    for (i = 0; i < 5; i++) {
        pthread_create(&pt[i], NULL, &thread_fun, (void*)i);
    }

}

JNIEXPORT void JNICALL native_setJniEnv
        (JNIEnv *env, jobject obj)
{
    LOGI("native_setJniEnv");
    //保存JVM
    (*env) -> GetJavaVM(env, &g_jvm);
    //保持actvity对象
    g_obj = (*env) -> NewGlobalRef(env, obj);

}



static const JNINativeMethod gMethods_MainActivity[] = {
        {
                "newJniThread","()V",(void*)native_newThead
        },
        {
                "setJniEnv", "()V",(void*)native_setJniEnv
        }
};


//注册mainactivity中的native方法
static int registerNatives_Main(JNIEnv* engv)
{
    LOGI("registerNatives_Main begin");
    jclass  clazz;
    clazz = (*engv) -> FindClass(engv, "com/dn/tim/dn_lsn_9/MainActivity");

    if (clazz == NULL) {
        LOGI("clazz is null");
        return JNI_FALSE;
    }

    if ((*engv) ->RegisterNatives(engv, clazz, gMethods_MainActivity, NELEM(gMethods_MainActivity)) < 0) {
        LOGI("registerNatives_Main error");
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{

    LOGI("jni_OnLoad begin");

    JNIEnv* env = NULL;
    jint result = -1;

    if ((*vm)->GetEnv(vm,(void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOGI("ERROR: GetEnv failed\n");
        return -1;
    }
    assert(env != NULL);

    registerNatives_Main(env);

    return JNI_VERSION_1_4;
}


发布了269 篇原创文章 · 获赞 123 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/baopengjian/article/details/105017994