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