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

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

2013-09-07 16:09 519 查看

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

 

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

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

 

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;

/**

 
*数据传输

 
*

 
*@author luxiaofeng <454162034@qq.com>

 
*

 
*/

public
 
class
 
MainActivity
extends
 
Activity {

    
 
    
//也就是你mk配置文件中的  LOCAL_MODULE    := NDK_06

    
private
 
static
 
final
 
String libSoName =
"NDK_06"
;

    
private
 
Context mContext =
null
;

    
 
    
private
 
int
 
num =
0
;

    
private
 
int
[] nums;

    
 
    
private
 
Button btnCalculate =
null
;

    
private
 
Button btnCalculateArray =
null
;

    
private
 
EditText etNum =
null
;

    
private
 
EditText etArrayNum =
null
;

    
private
 
TextView tvDoubleNum =
null
;

    
private
 
TextView tvArrayDoubleNum =
null
;

    
 
    
 
    
/**Called when the activity is first created. */

    
@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
(NumberFormatException e) {

            
etNum.setText(
""
);

            
tvDoubleNum.setText(
""
);

            
LogUtils.toastMessage(mContext,
"输入有误,请重新输入数字"
);

            
return
 
false
;

        
}

        
return
 
true
;

    
}

    
 
    
private
 
void
 
setNum() {

        
int
 
doubleNum = getDoubleNumber(num);

        
LogUtils.printWithLogCat(
"JNIMsg"
,
"C JNI -- >  Java: num = "
+doubleNum);

        
tvDoubleNum.setText(String.valueOf(doubleNum));

    
}

    
 
    
private
 
boolean
 
getArrayNums() {

        
String str =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
(NumberFormatException e) {

                
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
 
;

        
}

        
 
        
String str =
""
;

        
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倍的数字

     
*

     
*@param num

     
*

     
*@return

     
*/

    
public
 
native
 
int
 
getDoubleNumber(
int
 
num);

    
 
    
 
    
/**

     
*计算2倍的数组值

     
*

     
*@param num

     
*

     
*@return

     
*/

    
public
 
native
 
int
[] getArrayDoubleNumber(
int
[]
nums);

    
 
    
/**

     
*载入JNI生成的so库文件

     
*/

    
static
 
{

        
System.loadLibrary(libSoName);

    
}

}


       定义两个native方法, 第一个是 用来 测试传输 基本数据类型的,第二个是用来测试 传输数组的。

      

       Android.mk 文件

      

?
LOCAL_PATH := $(call my-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,jobject thiz,jint num )

{

    
if
(jniEnv == NULL) {

        
jniEnv = env;

    
}

    
//获取 Java 传递下来 数字

    
__android_log_print(ANDROID_LOG_INFO,
"JNIMsg"
,
"Java -- > C JNI : num = %d"
,num);

    
//返回 2 倍 的数字给 Java

    
return
 
num*2;

}

 
jintArray

Java_com_duicky_MainActivity_getArrayDoubleNumber( JNIEnv*env,jobject thiz,jintArray nums )

{

    
if
(jniEnv == NULL) {

        
jniEnv = env;

    
}

 
    
if
(nums == NULL){

        
return
 
NULL;

    
}

 
    
//获取 Java 传递下来 数组 的 长度

    
jsize len = (*jniEnv)->GetArrayLength(jniEnv, nums);

 
    
__android_log_print(ANDROID_LOG_INFO,
"JNIMsg"
,
"Java -- > C JNI : len = %d"
,len);

 
    
if
(len <= 0) {

        
return
 
NULL;

    
}

 
    
//新建一个长度为len的jintArray数组

    
jintArray array = (*jniEnv)-> NewIntArray(jniEnv, len);

 
    
if
(array == NULL) {

        
return
 
NULL;

    
}

 
    
// 把 Java 传递下来的数组 用 jint*存起来

    
jint *body = (*env)->GetIntArrayElements(env, nums, 0);

 
    
jint i = 0;

    
jint num[len];

    
for
 
(; i < len; i++) {

        
num[i] = body[i] *2;

        
__android_log_print(ANDROID_LOG_INFO,
"JNIMsg"
,
"Java -- > C JNI : 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,jobject thiz) 后面添加 如:(JNIEnv*env,jobject thiz,jintArray nums )

2)  获取数组的长度 jsize len = (*jniEnv)->GetArrayLength(jniEnv, nums);

3)  新建数组 jintArray array = (*jniEnv)-> NewIntArray(jniEnv, len); 如果是新建别的数组,NewIntArray 要做相对应的改变

4)  获取 数组里面的元素:

1.         (*env)->GetIntArrayElements(env, nums, isCopy) , 返回 所有数据。If isCopy is not NULL, then *isCopy is set to JNI_TRUE if a copy is made; if no copy is made, it is set
to JNI_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 博客 , 转载请注明出处 http://www.cnblogs.com/luxiaofeng54/archive/2011/08/19/2145486.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐