您的位置:首页 > 移动开发 > Android开发

基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)

2011-11-01 10:07 573 查看



/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

package
com.duicky;
import
android.app.Activity;
import
android.content.Context;
import
android.os.Bundle;
import
android.view.View;
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
int
num=
0
;
private
int
[]nums;
private
ButtonbtnCalculate=
null
;
private
ButtonbtnCalculateArray=
null
;
private
EditTextetNum=
null
;
private
EditTextetArrayNum=
null
;
private
TextViewtvDoubleNum=
null
;
private
TextViewtvArrayDoubleNum=
null
;
/**Calledwhentheactivityisfirstcreated.*/
@Override
public
void
onCreate(BundlesavedInstanceState){
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext=
this
;
initViews();
}
/**
*初始化控件
*/
private
void
initViews(){
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(){
if
(getArrayNums()){
setArrayNums();
}
}
private
void
calculate(){
if
(getNum()){
setNum();
}
}
private
boolean
getNum(){
try
{
num=Integer.valueOf(etNum.getText().toString());
}
catch
(NumberFormatExceptione){
etNum.setText(
""
);
tvDoubleNum.setText(
""
);
LogUtils.toastMessage(mContext,
"输入有误,请重新输入数字"
);
return
false
;
}
return
true
;
}
private
void
setNum(){
int
doubleNum=getDoubleNumber(num);
LogUtils.printWithLogCat(
"JNIMsg"
,
"CJNI-->Java:num="
+doubleNum);
tvDoubleNum.setText(String.valueOf(doubleNum));
}
private
boolean
getArrayNums(){
Stringstr=etArrayNum.getText().toString();
if
(str.length()<=
0
){
etArrayNum.setText(
""
);
tvArrayDoubleNum.setText(
""
);
LogUtils.toastMessage(mContext,
"请按照格式输入"
);
return
false
;
}
System.out.println(str);
if
(str.endsWith(
"."
)){
str=str.substring(
0
,str.length()-
2
);
}
System.out.println(str);
String[]strArray=str.split(
","
);
int
len=strArray.length;
nums=
new
int
[len];
for
(
int
i=
0
;i<len;i++){
try
{
nums[i]=Integer.valueOf(strArray[i]);
System.out.println(nums[i]);
}
catch
(NumberFormatExceptione){
etArrayNum.setText(
""
);
tvArrayDoubleNum.setText(
""
);
LogUtils.toastMessage(mContext,
"输入有误,请重新输入数组"
);
return
false
;
}
}
return
true
;
}
private
void
setArrayNums(){
int
[]doubleArrayNums=getArrayDoubleNumber(nums);
if
(doubleArrayNums==
null
||doubleArrayNums.length<=
0
){
LogUtils.toastMessage(mContext,
"未转化成功"
);
return
;
}
Stringstr=
""
;
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{
@Override
public
void
onClick(Viewv){
switch
(v.getId()){
case
R.id.btn_calculate:
calculate();
break
;
case
R.id.btn_calculate_array:
calculateArray();
break
;
}
}
}
/**
*计算2倍的数字
*
*@paramnum
*
*@return
*/
public
native
int
getDoubleNumber(
int
num);
/**
*计算2倍的数组值
*
*@paramnum
*
*@return
*/
public
native
int
[]getArrayDoubleNumber(
int
[]nums);
/**
*载入JNI生成的so库文件
*/
static
{
System.loadLibrary(libSoName);
}
}
定义两个native方法,第一个是用来测试传输基本数据类型的,第二个是用来测试传输数组的。

Android.mk文件

LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include
LOCAL_LDLIBS+=-L$(SYSROOT)/usr/lib-llog
LOCAL_MODULE:=NDK_06
LOCAL_SRC_FILES:=\
Transmission.c
include$(BUILD_SHARED_LIBRARY)
老样子,不说了,你懂的。如果不懂,嘎嘎,那就请点击Android.mk文件简介咯

JNI中间层

Transmission.c

#include<string.h>
#include<jni.h>
#include<android/log.h>
JNIEnv*jniEnv;
jint
Java_com_duicky_MainActivity_getDoubleNumber(JNIEnv*env,jobjectthiz,jintnum)
{
if
(jniEnv==NULL){
jniEnv=env;
}
//获取Java传递下来数字
__android_log_print(ANDROID_LOG_INFO,
"JNIMsg"
,
"Java-->CJNI:num=%d"
,num);
//返回2倍的数字给Java
return
num*2;
}
jintArray
Java_com_duicky_MainActivity_getArrayDoubleNumber(JNIEnv*env,jobjectthiz,jintArraynums)
{
if
(jniEnv==NULL){
jniEnv=env;
}
if
(nums==NULL){
return
NULL;
}
//获取Java传递下来数组的长度
jsizelen=(*jniEnv)->GetArrayLength(jniEnv,nums);
__android_log_print(ANDROID_LOG_INFO,
"JNIMsg"
,
"Java-->CJNI:len=%d"
,len);
if
(len<=0){
return
NULL;
}
//新建一个长度为len的jintArray数组
jintArrayarray=(*jniEnv)->NewIntArray(jniEnv,len);
if
(array==NULL){
return
NULL;
}
//把Java传递下来的数组用jint*存起来
jint*body=(*env)->GetIntArrayElements(env,nums,0);
jinti=0;
jintnum[len];
for
(;i<len;i++){
num[i]=body[i]*2;
__android_log_print(ANDROID_LOG_INFO,
"JNIMsg"
,
"Java-->CJNI:nums[%d]=%d"
,i,num[i]);
}
if
(num==NULL){
return
NULL;
}
//给需要返回的数组赋值
(*jniEnv)->SetIntArrayRegion(jniEnv,array,0,len,num);
return
array;
}

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中

有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐