android JNI学习之一

执行System.loadLibrary()函数时,VM会反向调用*.so里的JNI_OnLoad()函数。用途有二:
1. VM询问此*.so使用的JNI版本编号。
2. VM要求*.so做一些初期设定工作(Initialization),例如登记<函数名称表>。

•例如,在Android的jniload.so档案里,就提供了JNI_OnLoad()函数,其程序码片段为:

/* com.misoo.counter.CounterNative.cpp */
#include <stdio.h>
#include<jni.h>
#include <pthread.h>
#include<android/log.h>
#include "com_misoo_counter_CounterNative.h"
//LOGE("ERROR: GetEnv failed
");
#define LOGE(x)  __android_log_print(ANDROID_LOG_INFO,TAG,(x))
jmethodID mid;
jclass mClass;
JavaVM *jvm;
pthread_t thread;
int n, sum;
const char *TAG="JniTest";
//int  ANDROID_LOG_INFO= 0;
void* trRun(void*);
void JNICALL Java_com_misoo_counter_CounterNative_nativeSetup(JNIEnv *env,
        jobject thiz) {
    jclass clazz = env->GetObjectClass(thiz);
    mClass = (jclass) env->NewGlobalRef(clazz);
    mid = env->GetStaticMethodID(mClass, "callback", "(I)V");
}
void JNICALL Java_com_misoo_counter_CounterNative_nativeExec(JNIEnv *env,
        jobject thiz, jint numb) {
    n = numb;
    pthread_create(&thread, NULL, trRun, NULL);
}
void* trRun(void*) {
    int status;
    JNIEnv *env;
    bool isAttached = false;
    status = jvm->GetEnv((void **) &env, JNI_VERSION_1_4);
    if (status < 0) {
        status = jvm->AttachCurrentThread(&env, NULL);
        if (status < 0)
            return NULL;
        isAttached = true;
    }
    sum = 0;
    for (int i = 0; i <= n; i++)
        sum += i;
    env->CallStaticVoidMethod(mClass, mid, sum);
    if (isAttached)
        jvm->DetachCurrentThread();
    return NULL;
}

static const char *classPathName = "com/misoo/counter/CounterNative";
static JNINativeMethod methods[] = { { "init", "()V",
        (void *) Java_com_misoo_counter_CounterNative_nativeSetup }, {
        "execute", "(I)V",
        (void *) Java_com_misoo_counter_CounterNative_nativeExec } };
static int registerNativeMethods(JNIEnv* env, const char* className,
        JNINativeMethod* gMethods, int numMethods) {
    __android_log_print(ANDROID_LOG_INFO,TAG,"registerNativeMethods");
    if(env == NULL)
        __android_log_print(ANDROID_LOG_INFO,TAG,"env is null");
    jclass clazz = env->FindClass(className);
    __android_log_print(ANDROID_LOG_INFO,TAG,"find class");
    __android_log_print(ANDROID_LOG_INFO,TAG,"%s",className);
    env->RegisterNatives(clazz, gMethods, numMethods);
    __android_log_print(ANDROID_LOG_INFO,TAG,"end registerNativeMethods");
    return JNI_TRUE;
}
static int registerNatives(JNIEnv* env) {
    __android_log_print(ANDROID_LOG_INFO,TAG,"registerNatives");
    registerNativeMethods(env, classPathName, methods,
            sizeof(methods) / sizeof(methods[0]));
    __android_log_print(ANDROID_LOG_INFO,TAG,"end registerNatives");
    return JNI_TRUE;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    __android_log_print(ANDROID_LOG_INFO,TAG,"JNI_OnLoad");
    JNIEnv *env = NULL;
    jvm = vm;
     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
            LOGE("ERROR: GetEnv failed
");
//            return -1;
        }
//    assert(env == NULL);
    if (registerNatives(env) != JNI_TRUE)
        return -1;
    __android_log_print(ANDROID_LOG_INFO,TAG,"JNI_OnLoad end");
    return JNI_VERSION_1_4;
}



Android.mk文件是:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog
LOCAL_MODULE    :=jniload
LOCAL_SRC_FILES :=archMultiThread.cpp

include $(BUILD_SHARED_LIBRARY)

Application.mk文件:

APP_STL:=gnustl_static  
APP_CPPFLAGS:=-frtti -fexceptions  
APP_ABI:=armeabi armeabi-v7a
APP_PLATFORM=android-8

CounterNative.java

package com.misoo.counter;

import com.example.hellondk.MainActivity;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

//CounterNative.java 
// ……… 
public class CounterNative {
    private static Handler h;
    public static final String TAG = "JniTest";
    static {
        Log.i(CounterNative.TAG, "try to load libMyJT002.so");
        System.loadLibrary("jniload");
        Log.i(CounterNative.TAG, "end try to load libMyJT002.so");
    }

    public CounterNative() {
        Log.i(CounterNative.TAG, "new CounterNative");
        init();
        Log.i(CounterNative.TAG, "init finished");

        h = new Handler() {
            public void handleMessage(Message msg) {
                MainActivity.ref.setTitle("Hello …");
            }
        };
    }

    private static void callback(int a) {
        Message m = h.obtainMessage(1, a, 3, null);
        h.sendMessage(m);
    }

    private native void init();

    public native void execute(int numb);
}
package com.example.hellondk;

import java.sql.Ref;

import com.huml.ndk1.NativeJniAdder;
import com.misoo.counter.CounterNative;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends Activity {
    public static MainActivity ref = null;
    CounterNative obj;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ref= this;
        Log.i(CounterNative.TAG, "onCreate");
        obj = new CounterNative();
    }

//对应一个Button的onClick事件,布局文件中一个Button按钮,布局文件很简单我就不列出来了
    public void TestNDK(View view){
        Log.i(NativeJniAdder.TAG, "start NDK");
        obj.execute(11);
    }
    
}
原文地址:https://www.cnblogs.com/ronaldHU/p/5052754.html