Native層與java層之間的資料傳遞程式碼例項
阿新 • • 發佈:2019-01-23
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