1. 程式人生 > >Native層與java層之間的資料傳遞程式碼例項

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