android ndk开发静态注册与动态注册

android ndk开发java调用c/c++的本地方法,存在两种方法,静态注册,和动态注册,framewor层采用的是后者。下面我们就两种方式做一下演示。

实现功能是点击按钮,改变TextView字符,并弹Toast提示。

MainActivity中System.loadLibrary(“native-lib”),声明native方法,还有一个tip,方法是给native调用的。完成一个交互

package com.example.client.jnitest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
       final  TextView tv =  findViewById(R.id.sample_text);
        Button testBt = findViewById(R.id.test_bt);
        testBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText(stringFromJNI());

            }
        });

    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    public void tip(){
        Toast.makeText(this,"from_native",Toast.LENGTH_LONG).show();
    }
}

native这边我们实现native方法,静态注册需要在方法头部加JNIEXPORT JNICALL 等关键字。

#include <jni.h>
#include <string>

#include <stdlib.h>

jmethodID getNameID;
jclass mainActivity;

void callJava(JNIEnv *env,jobject obj){
    mainActivity= env->FindClass("com/example/client/jnitest/MainActivity");
    getNameID=env->GetMethodID(mainActivity,"tip","()V");
    env->CallVoidMethod(obj,getNameID);
}




extern "C" JNIEXPORT jstring JNICALL
Java_com_example_client_jnitest_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject jobject1) {
    callJava(env,jobject1);

    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

项目目录如下
在这里插入图片描述

下面展示动态注册的代码
native_hello方法名随便定义,他是实现java层 stringFromJNI 方法的调用,它们之间的绑定借助于JNI_OnLoad方法,JNI_OnLoad会在java那边System.loadLibrary时候被调用,建立关联关系。

#include <jni.h>
#include <string>

#include <stdlib.h>

jmethodID getNameID;
jclass mainActivity;

void callJava(JNIEnv *env,jobject obj){
    mainActivity= env->FindClass("com/example/client/jnitest/MainActivity");
    getNameID=env->GetMethodID(mainActivity,"tip","()V");
    env->CallVoidMethod(obj,getNameID);
}


jstring native_hello(JNIEnv *env, jobject object) {
    callJava(env,object);
    return env->NewStringUTF("Hello from C++");
}


JNINativeMethod method[]={{"stringFromJNI","()Ljava/lang/String;",(void*)native_hello}};

jint registerNativeMeth(JNIEnv *env){
    jclass cl=env->FindClass("com/example/client/jnitest/MainActivity");
    if((env->RegisterNatives(cl,method,1))<0){
        return -1;
    }
    return 0;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    if (registerNativeMeth(env) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_4;
}

另外关于jni调用,是结合函数dlopen. dlsym 加载so库,并查找函数指针调用。

猜你喜欢

转载自blog.csdn.net/atxxiang4/article/details/85375147