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