基于 Android NDK 的学习之旅-----数据传输一(基本数据类型和数组传输)(附源码)
来源:互联网 发布:美国枪击案与网络恶搞 编辑:程序博客网 时间:2024/05/01 09:08
基于 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_06private 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{@Overridepublic 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)/includeLOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llogLOCAL_MODULE := NDK_06LOCAL_SRC_FILES := \Transmission.cinclude $(BUILD_SHARED_LIBRARY)
老样子,不说了,你懂的。如果不懂,嘎嘎,那就请点击Android.mk文件 简介咯
JNI 中间层
Transmission.c
#include <string.h>#include <jni.h>#include <android/log.h>JNIEnv* jniEnv;jintJava_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 倍 的数字给 Javareturn num*2;}jintArrayJava_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 博客 , 转载请注明出处
http://www.cnblogs.com/luxiaofeng54/archive/2011/08/19/2145486.html
- 基于 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 的学习之旅-----HelloWorld (附源码)
- 基于 Android NDK 的学习之旅-----JNI LOG 打印(附源码)
- 基于 Android NDK 的学习之旅-----Java 调用 C(附源码)
- 基于 Android NDK 的学习之旅----- C调用Java(附源码)
- 基于 Android NDK 的学习之旅----- Java 方法映射到C中的签名(附源码)
- 基于 Android NDK 的学习之旅----- Java 方法映射到C中的签名(附源码)
- sql优化,ordered user_nl() index() 的用法 ,示例 。
- 通过javascript获得url参数
- IEEE浮点数表示--规格化/非规格化/无穷大/NaN
- 如何查看Xcode4的文档问题
- 脚本动态生成VML
- 基于 Android NDK 的学习之旅-----数据传输一(基本数据类型和数组传输)(附源码)
- [转]Windows文件系统的杂谈
- 网上摘的。关于android屏幕翻转的。留着有好处。。。。
- Hibernate查询
- Thread-specific data
- String与Date类型互转
- Asp.net 算时间差 -- XXX小时前,XXX天以前,XXX分钟以前 发布
- P2P技术
- VC创建启动即隐藏的对话框(转)