Native層與java層之間的數據傳遞代碼實例

Native 層與 java 之間的 數據傳遞


MainActivity

package com.a18459.myapplication;

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

public class MainActivity extends AppCompatActivity {

    String name = "hello";

    NdkLib ndkLib;
    String string;
    TextView tv;
    Student student;

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

        //使用NDK
        ndkLib = new NdkLib();


//------------------------------從java層獲取Native層數據--------------------------------------

        //在Native層獲得字符串
        string = ndkLib.getNativeString();
        tv = (TextView) findViewById(R.id.tv);
        tv.setText(string);

        //在Native層獲得一維數組
        ndkLib.getArray(5);

        //在Native層獲得二維數組
        ndkLib.getTwoArray(5);

        //在Native層獲得類對象
        student = ndkLib.getStudentFromJNI();
        string = "id: "+ student.getId() + "\n" + "name: " + student.getName();
        tv.setText(string);


//------------------------------從Native層獲取java層數據-------------------------------------

        //在Native層操作java層的類中的屬性name的值
        Log.i("name: ", ndkLib.name);
        //在Native層修改了成員變量name的值
        ndkLib.Print();
        Log.i("name: ", ndkLib.name);

        //在Native層操作java層的類中的方法,
        ndkLib.doCallBack();
    }
}

NdkLib

package com.a18459.myapplication;

import android.util.Log;

/**
 * Created by 18459 on 2016/7/1.
 */
public class NdkLib {
    //加載ndk庫
    static{
        System.loadLibrary("ndk_lib");
    }
    //定義ndk庫中的導出函數
    //獲得字符串
    public native String getNativeString();
    //獲得一維數組
    public native int[] getArray(int nSize);
    //獲得二維數組
    public native int[][] getTwoArray(int nSize);
    //獲得類對象
    public native Student getStudentFromJNI();

//---------------------------------------------------------------------------------

    //在Native層操作java層的類,改變類中的屬性name的值
    public native void Print();
    String name = "hello";

    //在Native層操作java層的類中的方法,
    public native void doCallBack();
    //Native層會調用callback()方法
    public void CallBack(String string){
        Log.i("CallBack2",string);
    }
}

Student

package com.a18459.myapplication;

/**
 * Created by 18459 on 2016/7/2.
 */
public class Student {

    public Student(){}

    public Student(int id,String name){
        this.id = id;
        this.name = name;
    }

    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Jni目錄下:

ndk_lib.cpp

#include <jni.h>
#include <android/log.h>
#include <string.h>

extern "C" JNIEXPORT jstring JNICALL
Java_com_a18459_myapplication_NdkLib_getNativeString(JNIEnv *env, jobject instance) {
    return env->NewStringUTF("我是字符串");
}

//返回一維數組
extern "C" JNIEXPORT jintArray JNICALL
Java_com_a18459_myapplication_NdkLib_getArray(JNIEnv *env, jobject instance, jint nSize) {
    //構建jint型一維數組
    jintArray intArray =env->NewIntArray(nSize);
    jint temp[10]  ;  //初始化一個容器,假設 dimion  < 10 ;
    for( int j = 0 ; j < nSize ; j++)
    {
        temp[j] = j  ;
        __android_log_print(ANDROID_LOG_DEBUG,"hellondk","data! %d", temp[j]);
    } //賦值
    //設置jint型一維數組的值
    env->SetIntArrayRegion(intArray, 0 , nSize ,temp);

    // 必須有返回值!!
    return intArray;

}

// 返回二維數組,即返回對象數組,因爲沒有JNI類型直接表示二維數組
extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_a18459_myapplication_NdkLib_getTwoArray(JNIEnv *env, jobject instance, jint nSize) {

    // 獲取一維數組的class類型
    jclass jArrayClass = env->FindClass("[I");//數組的域描述符
    // 創建二維數組
    jobjectArray jobjectArray1;
    jobjectArray1 = env->NewObjectArray(nSize, jArrayClass,0);
    // 初始化數組
    for (int i = 0; i <nSize ; ++i) {
        // 構造二維數組的數組元素,即一維數組
        //構建jint型一維數組
        jintArray intArray = env->NewIntArray(nSize);
        jint temp[10]  ;  //初始化一個容器,假設 dimion  < 10 ;
        for( int j = 0 ; j < nSize ; j++)
        {
            temp[j] = j  ;
            __android_log_print(ANDROID_LOG_DEBUG,"hellondk","data! %d", temp[j]);
        } //賦值
        //設置jint型一維數組的值
        env->SetIntArrayRegion(intArray, 0 , nSize ,temp);
        // 設置對象數組的值
        env->SetObjectArrayElement(jobjectArray1,i,intArray);
        env->DeleteLocalRef(intArray);  //刪除局部引用
    }
    //要返回
    return jobjectArray1;
}

//返回類的對象
extern "C" JNIEXPORT jobject JNICALL
Java_com_a18459_myapplication_NdkLib_getStudentFromJNI(JNIEnv *env, jobject instance) {

    // 創建對象
    jobject jstudent;
    // 1.獲取類型
    jclass jsutdentclass = env->FindClass("com/a18459/myapplication/Student");
    // 2.通過類型獲取構造方法ID
    jmethodID jmethodID1 = env->GetMethodID(jsutdentclass,
            //<init>是指構造函數方法
                                            "<init>",
            //構造函數Student(int id,String name)的描述符,v代表返回值問void
                                            "(ILjava/lang/String;)V");
    jstring jname = env->NewStringUTF("我來自Student類");
    // 3.創建對象
    jstudent = env->NewObject(jsutdentclass,jmethodID1,1,jname);

    return jstudent;
}

//此方法應爲成員方法
//在Native層調用java層類中屬性,並修改值
extern "C" JNIEXPORT void JNICALL
Java_com_a18459_myapplication_NdkLib_Print(JNIEnv *env, jobject instance) {

    // 1.根據對象獲取類型
    jclass jobjectcls = env->GetObjectClass(instance);

    // 2.根據類型獲取域ID
    jfieldID jfieldID1 = env->GetFieldID(jobjectcls,"name","Ljava/lang/String;");

    // 3.根據域ID獲取成員變量
    jstring jstring1 = (jstring)env->GetObjectField(instance,jfieldID1);
    //int len = env->GetStringUTFLength(jstring1);
    // GetStringUTFChars 返回指針,直接操作NativeTypes字符串
    // GetStringUTFRegion 返回字符串內容,必須緩衝區有值
    char* name = (char*)env->GetStringUTFChars(jstring1,0);
    //Native層的log調試輸出
    //__android_log_print(ANDROID_LOG_DEBUG, "ndk_lib","NdkLib! %s", name);

    // 設置成員變量的值
    //構造一個jString對象
    char * c_ptr_name = "在Native層修改了java層成員變量name的值" ;
    jstring cName = env->NewStringUTF(c_ptr_name);
    // 設置該字段的值
    env->SetObjectField(instance , jfieldID1 , cName);
    //釋放局部引用
    env->ReleaseStringUTFChars(jstring1, name);
}

//此方法應爲成員方法
//在Native層調用java層類中方法,並給方法傳參數
extern "C"JNIEXPORT void JNICALL
Java_com_a18459_myapplication_NdkLib_doCallBack(JNIEnv *env, jobject instance) {

    // 1.根據對象獲取類型
    jclass jobjectcls = env->GetObjectClass(instance);

    // 2.根據類型獲取方法ID
    jmethodID jmethodID1 = env->GetMethodID(jobjectcls,
                                            "CallBack",
                                            "(Ljava/lang/String;)V");
    jstring jname = env->NewStringUTF("在Native層調用java層方法");
    // 3.根據方法ID調用方法,並傳遞參數
    env->CallVoidMethod(instance,jmethodID1,jname);
}

使用工具: android studio 2.1.2

實例代碼:鏈接:http://pan.baidu.com/s/1eSAxmxW 密碼:5bwp

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