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

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

2016-01-12 20:32 483 查看
之前的一些文章都有涉及到上层和中间层的数据传输,简单来说,也就是参数和返回值的使用。因为中间层要做的最多的也就是数据传输与转换,下面来介绍下这方面的知识。

数据传输可分为基本数据类型传输和引用数据类型的传输,因为数组传输也比较特别(其实数组也是引用类型),所以这里也专门分出来讲讲。

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
String
libSoName=
"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(Bundle
savedInstanceState){

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(View
v){

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中

有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,点击下载源码数据的传输一

本文出自duicky博客,转载请注明出处/article/5095942.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: