Android_JNI_1

Android JNI

  • JNI最为C++和java在Android中的桥梁,在整个开发过程中都是至关重要的,也是必须要去熟悉的地方。
  • 本篇主要记录下自己在学习的JNI中过程,本篇只是在单一主线程进行调用,下一篇将介绍多线程进行调用的情况,也希望可以帮助到有需要的人,仅此而已。

  1. Java调用C++代码

a. 在日常中对于一些对性能要求更高的地方,经常会采用C++来进行完成,那么此时就涉及到要使用java调用C++层API完成相应的动作。
b. 新建一个NativiUtils类完成具体API的设计,不和MainActivity混在一起
c. javc调用C++过程其实很简单,只是一个C++层具体代码的实现
d. 下面的环境是在Android Studio中进行操作,C++编译采用cmake完成编译。

MainActivity.java

package com.example.blogdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

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

    final NativeUtils nativeUtils = new NativeUtils();

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

        // Example of a call to a native method
        // 这里进行将C++层代码进行一个回显
        TextView textView = findViewById(R.id.sample_text);
        textView.setText(nativeUtils.jniJavaCallcPlus("skinWhite blog"));

    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */

}

NativeUtils.java

package com.example.blogdemo;

// TODO
// 1. 完成native方法的设计
// 2. 实现该方法

public class NativeUtils {

	// 这里设计native的API,至于C++层的方法头,可以使用alt+enter自动生成
    public native String jniJavaCallcPlus(String Helloname);
}

native-lib.cpp

#include 
#include 
#include 
// TODO
// 1.  C++层代码具体实现


extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_momo_blogdemo_NativeUtils_jniJavaCallcPlus(JNIEnv *env, jobject instance,
                                                            jstring Helloname_) {
    // 1. C++层的代码实现
    jboolean isCopy;
    std::string helloName = env->GetStringUTFChars(Helloname_,&isCopy);


    return env->NewStringUTF(helloName.data());
}
  1. C++调用Java代码

a. 应为C++层不能通过native直接调用java代码,所以需要进行一些而外的操作
b. 其次本demo不考虑多线程情况下的调用,将在下一篇进行多线程的介绍。
c. 在实现C++调用java时只需按照下文5步操作,但是要完成JNI层参数对照。
d. 在获取类的字节码码时,注意中间用’ / ‘,而不是’ _ '。
f. 如果要自己完成Cpp文件的话,注意要在CmakeLists.txt中倒入源文件路径,在MainActivity记得静态加载库。

MainActivity.java

package com.example.blogdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity {

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

    final NativeUtils nativeUtils = new NativeUtils();
    public static TextView textView = null;

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

        // Example of a call to a native method
        textView = findViewById(R.id.sample_text);
        nativeUtils.jniJavaCallcPlus("SkinWhite blog");

    }

}

NativeUtils.java

package com.example.momo.blogdemo;

import android.os.Handler;
import android.os.Looper;


public class NativeUtils {

    public static Handler uiHandler = new Handler(Looper.getMainLooper());

    // Java层调用C++
    public native void jniJavaCallcPlus(String Helloname);
    // C++层调用Java
    public void jnicPlusCallJava(final String Helloname){
        // 具体实现(UI刷新)
        uiHandler.post(new Runnable() {
            @Override
            public void run() {
            	 
                MainActivity.textView.setText(Helloname);
            }
        });

    }
}

#include 
#include 
#include 

extern "C"
JNIEXPORT void JNICALL
Java_com_example_momo_blogdemo_NativeUtils_jniJavaCallcPlus(JNIEnv *env, jobject instance,
                                                            jstring Helloname_) {

    // TODO
    // 1. 拿到class的字节码
    jclass cls = env->FindClass("com/example/momo/blogdemo/NativeUtils");
    // 2. 获取methodId,最后一个参数可以参照JNI对照表
    jmethodID mid = env->GetMethodID(cls,"jnicPlusCallJava","(Ljava/lang/String;)V");
    // 3. 实例化对象
    jobject obj = env->AllocObject(cls);
    // 4. 构造方法参数(因为本身即使jstring对象,所以不用转换)

    // 5. 调用方法
    env->CallVoidMethod(obj,mid,Helloname_);
}

> 上述代码其实是是C++的异步调用了Java层。整个过程是Java层先调用一个nativa方法,native方法里回调java层的代码,完成C++调用java的实现。

你可能感兴趣的:(Android)