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

本文详细介绍Java与JNI间基本数据类型及数组的传输方法,包括流程、实现代码与运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

 

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 中

 

 

有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,

 

点击下载源码 数据的传输一

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值