/article/5095942.html
之前的一些文章都有涉及到上层和中间层的数据传输,简单来说,也就是参数和返回值的使用。因为中间层要做的最多的也就是数据传输与转换,下面来介绍下这方面的知识。
数据传输可分为基本数据类型传输和引用数据类型的传输,因为数组传输也比较特别(其实数组也是引用类型),所以这里也专门分出来讲讲。
1、主要流程
1、基本数据类型的传输
a)上层定义一个native的方法,需要一个int参数,返回一个int值
b)JNI对应上层的方法,打印出上层传输下来的int数据,并返回int数据
c)上层收到native方法返回的值,在UI中显示出来
2、数组的传输
a)上层定义一个native的方法,需要一个int数组,返回一个int数组
b)JNI对应上层的方法,取出上层传递数组中的数据处理和打印出来,并存入新数组中,最后把该数组返回给Java层
c)上层收到native返回的数组,加工成字符串,在UI中显示出来
2设计实现
1、界面设计如下:
老老样子,很搓,嘿嘿
代码不在这贴出了,有需要的兄弟直接到文章结束部分下载。
2、关键代码说明
Java上层:
public native int getDoubleNumber( int num); |
public native int []getArrayDoubleNumber( int []nums); |
MainActivity.java
import android.app.Activity; |
import android.content.Context; |
import android.view.View.OnClickListener; |
import android.widget.Button; |
import android.widget.EditText; |
import android.widget.TextView; |
*@authorluxiaofeng<454162034@qq.com> |
public class MainActivity extends Activity{ |
//也就是你mk配置文件中的LOCAL_MODULE:=NDK_06 |
private static final StringlibSoName= "NDK_06" ; |
private ContextmContext= null ; |
private ButtonbtnCalculate= null ; |
private ButtonbtnCalculateArray= null ; |
private EditTextetNum= null ; |
private EditTextetArrayNum= null ; |
private TextViewtvDoubleNum= null ; |
private TextViewtvArrayDoubleNum= null ; |
/**Calledwhentheactivityisfirstcreated.*/ |
public void onCreate(BundlesavedInstanceState){ |
super .onCreate(savedInstanceState); |
setContentView(R.layout.main); |
btnCalculate=(Button)findViewById(R.id.btn_calculate); |
btnCalculateArray=(Button)findViewById(R.id.btn_calculate_array); |
etNum=(EditText)findViewById(R.id.et_num); |
etArrayNum=(EditText)findViewById(R.id.et_array_num); |
tvDoubleNum=(TextView)findViewById(R.id.tv_double_num); |
tvArrayDoubleNum=(TextView)findViewById(R.id.tv_array_double_num); |
btnCalculate.setOnClickListener( new MyOnClickListener()); |
btnCalculateArray.setOnClickListener( new MyOnClickListener()); |
private void calculateArray(){ |
num=Integer.valueOf(etNum.getText().toString()); |
} catch (NumberFormatExceptione){ |
LogUtils.toastMessage(mContext, "输入有误,请重新输入数字" ); |
int doubleNum=getDoubleNumber(num); |
LogUtils.printWithLogCat( "JNIMsg" , "CJNI-->Java:num=" +doubleNum); |
tvDoubleNum.setText(String.valueOf(doubleNum)); |
private boolean getArrayNums(){ |
Stringstr=etArrayNum.getText().toString(); |
tvArrayDoubleNum.setText( "" ); |
LogUtils.toastMessage(mContext, "请按照格式输入" ); |
str=str.substring( 0 ,str.length()- 2 ); |
String[]strArray=str.split( "," ); |
nums[i]=Integer.valueOf(strArray[i]); |
System.out.println(nums[i]); |
} catch (NumberFormatExceptione){ |
tvArrayDoubleNum.setText( "" ); |
LogUtils.toastMessage(mContext, "输入有误,请重新输入数组" ); |
private void setArrayNums(){ |
int []doubleArrayNums=getArrayDoubleNumber(nums); |
if (doubleArrayNums== null ||doubleArrayNums.length<= 0 ){ |
LogUtils.toastMessage(mContext, "未转化成功" ); |
for ( int i= 0 ;i<doubleArrayNums.length;i++){ |
str+=doubleArrayNums[i]+ "." ; |
str=str.substring( 0 ,str.length()- 1 ); |
tvArrayDoubleNum.setText(str); |
class MyOnClickListener implements OnClickListener{ |
public void onClick(Viewv){ |
case R.id.btn_calculate_array: |
public native int getDoubleNumber( int num); |
public native int []getArrayDoubleNumber( int []nums); |
System.loadLibrary(libSoName); |
定义两个native方法,第一个是用来测试传输基本数据类型的,第二个是用来测试传输数组的。
Android.mk文件
LOCAL_PATH:=$(callmy-dir) |
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include |
LOCAL_LDLIBS+=-L$(SYSROOT)/usr/lib-llog |
include$(BUILD_SHARED_LIBRARY) |
老样子,不说了,你懂的。如果不懂,嘎嘎,那就请点击Android.mk文件简介咯
JNI中间层
Transmission.c
Java_com_duicky_MainActivity_getDoubleNumber(JNIEnv*env,jobjectthiz,jintnum) |
__android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "Java-->CJNI:num=%d" ,num); |
Java_com_duicky_MainActivity_getArrayDoubleNumber(JNIEnv*env,jobjectthiz,jintArraynums) |
jsizelen=(*jniEnv)->GetArrayLength(jniEnv,nums); |
__android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "Java-->CJNI:len=%d" ,len); |
jintArrayarray=(*jniEnv)->NewIntArray(jniEnv,len); |
jint*body=(*env)->GetIntArrayElements(env,nums,0); |
__android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "Java-->CJNI:nums[%d]=%d" ,i,num[i]); |
(*jniEnv)->SetIntArrayRegion(jniEnv,array,0,len,num); |
3、运行结果
测试基本数据类型传输:输入22,点击计算得出结果44
查看打印信息:看到上层输出结果
测试引用数据类型传输:输入11,22,33,44,55(逗号是在英文状态下半角输入),点击生成,输出22,44,66,88,100
查看打印信息:看到JNI层输出结果
以上就是Java---JNI基本数据类型和数组传输的小例子,其他基本数据类型和数组都可以仿照上面的做法传输。
4、注意点
你必须知道的是:
1)添加参数在(JNIEnv*env,jobjectthiz)后面添加如:(JNIEnv*env,jobjectthiz,jintArraynums)
2)获取数组的长度jsizelen=(*jniEnv)->GetArrayLength(jniEnv,nums);
3)新建数组jintArrayarray=(*jniEnv)->NewIntArray(jniEnv,len);如果是新建别的数组,NewIntArray要做相对应的改变
4)获取数组里面的元素:
1.(*env)->GetIntArrayElements(env,nums,isCopy),返回所有数据。IfisCopyisnotNULL,then*isCopyissettoJNI_TRUEifacopyismade;ifnocopyismade,itissettoJNI_FALSE.
2.(*env)->GetIntArrayRegion(env,array,start,len,buffer),从start开始复制长度为len的数据到buffer中
5)设置数组里面的元素
1.(*env)->SetIntArrayRegion(env,array,start,len,buffer),从start开始复制长度为len的数据buffer到array中
有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理