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

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

2011-08-19 11:53 561 查看

基于 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 ismade; 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 博客 , 转载请注明出处

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