基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
来源:互联网 发布:加入域找不到网络名 编辑:程序博客网 时间:2024/05/16 13:59
之前的一些文章都有涉及到上层和中间层的数据传输,简单来说,也就是参数和返回值的使用。因为中间层要做的最多的也就是数据传输与转换,下面来介绍下这方面的知识。
数据传输可分为 基本数据类型传输 和 引用数据类型的传输 , 因为数组传输也比较特别(其实数组也是引用类型),所以这里也专门分出来讲讲。
1、主要流程
<!--[if !supportLists]-->1、 <!--[endif]-->基本数据类型的传输
<!--[if !supportLists]-->a) <!--[endif]-->上层定义一个native的方法,需要一个int 参数 ,返回一个int值
<!--[if !supportLists]-->b) <!--[endif]-->JNI 对应 上层的方法 , 打印出 上层 传输下来的 int数据,并返回 int数据
<!--[if !supportLists]-->c) <!--[endif]-->上层 收到 native 方法 返回的 值,在UI中显示出来
<!--[if !supportLists]-->2、 <!--[endif]-->数组的传输
<!--[if !supportLists]-->a) <!--[endif]-->上层定义一个native的方法,需要一个int数组,返回一个int数组
<!--[if !supportLists]-->b) <!--[endif]-->JNI 对应上层的方法,取出上层传递数组中的数据处理和打印出来,并存入新数组中,最后把该数组返回给 Java层
<!--[if !supportLists]-->c) <!--[endif]-->上层 收到 native返回的 数组,加工成字符串,在UI中显示出来
2设计实现
<!--[if !supportLists]-->1、 <!--[endif]-->界面设计如下:
<!--[endif]-->
老老样子,很搓,嘿嘿
代码不在这贴出了,有需要的兄弟直接到文章结束部分下载。
<!--[if !supportLists]-->2、 <!--[endif]-->关键代码说明
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
<!--[endif]-->
查看 打印 信息 :看到 上层输出 结果
<!--[endif]-->
测试 引用数据类型传输:输入11,22,33,44,55 ( 逗号是在英文状态下半角输入) ,点击生成, 输出 22,44,66,88,100
<!--[endif]-->
查看 打印信息 : 看到JNI层输出 结果
<!--[endif]-->
以上就是 Java --- JNI 基本数据类型 和 数组 传输的 小例子 , 其他 基本数据类型和数组 都可以仿照上面的做法传输。
4、注意点
你必须知道的是:
<!--[if !supportLists]-->1) <!--[endif]-->添加参数在(JNIEnv* env,jobject thiz) 后面添加 如:(JNIEnv* env,jobject thiz,jintArray nums )
<!--[if !supportLists]-->2) <!--[endif]-->获取数组的长度 jsize len = (*jniEnv)->GetArrayLength(jniEnv, nums);
<!--[if !supportLists]-->3) <!--[endif]-->新建数组 jintArray array = (*jniEnv)-> NewIntArray(jniEnv, len); 如果是新建别的数组,NewIntArray 要做相对应的改变
<!--[if !supportLists]-->4) <!--[endif]-->获取 数组里面的元素:
<!--[if !supportLists]-->1. <!--[endif]-->(*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.
<!--[if !supportLists]-->2. <!--[endif]--> (*env)->GetIntArrayRegion(env,array,start,len,buffer) , 从start开始复制长度为len 的数据到buffer中
<!--[if !supportLists]-->5) <!--[endif]-->设置 数组里面的元素
<!--[if !supportLists]-->1. <!--[endif]-->(*env)->SetIntArrayRegion(env, array,start,len,buffer) , 从start开始复制长度为len 的数据 buffer到 array 中
有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,
点击下载源码 数据的传输一
- 基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
- 基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
- 基于Android NDK的学习之旅---数据传输一(基本数据类型和数组传输)
- 基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
- 基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
- 基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
- 基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
- 基于 Android NDK 的学习之旅-----数据传输一(基本数据类型和数组传输)(附源码)
- 基于 Android NDK 的学习之旅-----数据传输一(基本数据类型和数组传输)(附源码)
- 基于 Android NDK 的学习之旅-----数据传输二(引用数据类型)(附源码)
- 基于 Android NDK 的学习之旅-----数据传输(引用数据类型)
- 基于 Android NDK 的学习之旅-----数据传输(引用数据类型)
- Android NDK 的学习之旅-----数据传输
- 基于 Android NDK 的学习之旅-----JNI 数据类型
- 基于 Android NDK 的学习之旅-----JNI 数据类型
- 基于 Android NDK 的学习之旅-----JNI 数据类型
- 基于 Android NDK 的学习之旅-----JNI 数据类型
- 基于 Android NDK 的学习之旅-----JNI 数据类型
- oracle11g 配置Enterprise manager
- 危急值
- android中XML属性总结(更新中)
- nginx配置一:nginx分割日志--linux平台
- ubuntu下vi乱码(abcd)解决办法
- 基于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
- Android: 用Intent实现Activity之间数据传递
- 异步套接字基础:select函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
- 基于 Android NDK 的学习之旅-----数据传输(引用数据类型)
- 看看老外是如何理解抽象类的
- 就业招聘网站收集:
- 基于 Android NDK 的学习之旅-----资源释放
- 倒填矩阵
- C++ 中list容器,自定义sort排序规则,stl中sort自定义排序规则