基于 Android NDK 的学习之旅-----数据传输(引用数据类型)

接着上篇文章继续讲。主要关于引用类型的数据传输,本文将介绍字符串传输和自定义对象的传输。

 

1、主要流程

<!--[if !supportLists]-->1、  <!--[endif]-->String 字符串传输

<!--[if !supportLists]-->a)         <!--[endif]-->上层定义一个native的方法,需要一个String  参数 ,返回一个String

<!--[if !supportLists]-->b)        <!--[endif]-->JNI对应上层的方法,打印出上层传输下来的String数据,并返回处理String数据

<!--[if !supportLists]-->c)         <!--[endif]-->上层 收到 native 方法 返回的 值,在UI中显示出来

 

 

<!--[if !supportLists]-->2、  <!--[endif]-->自定义对象的传输

<!--[if !supportLists]-->a)         <!--[endif]-->自定义一个对象Person

<!--[if !supportLists]-->b)        <!--[endif]-->上层定义一个native方法,参数Person,返回值Person

<!--[if !supportLists]-->c)         <!--[endif]-->JNI接收对象,打印出相关信息数据

<!--[if !supportLists]-->d)        <!--[endif]-->JNI 修改Person 对象数据,并返回到上层

<!--[if !supportLists]-->e)         <!--[endif]-->上层接收到数据后 在UI显示出来

 

 

2设计实现

<!--[if !supportLists]-->1、  <!--[endif]-->界面设计如下:


<!--[endif]-->

老老样子,很搓,嘿嘿

代码不在这贴出了,有需要的兄弟直接到文章结束部分下载。

<!--[if !supportLists]-->2、  <!--[endif]-->关键代码说明

 

Java 上层:

?
public native String transferString(String mStrMSG);
  
public native Object  transferPerson(Person mPerson);

  

Person.java

?
package com.duicky;
  
/**
 
 
  * @author luxiaofeng <454162034@qq.com>
 
  */
public class Person {
  
     private String name;
     private int age;
  
     public Person() {
         name = "" ;
         age = 0 ;
     }
  
     public String getName() {
         return name;
     }
  
     public void setName(String name) {
         this .name = name;
     }
  
     public int getAge() {
         return age;
     }
  
     public void setAge( int age) {
         this .age = age;
     }
  
     @Override
     public String toString() {
         return "Person [name=" + name + ", age=" + age + "]" ;
     }
  
}

  

定义两个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_07
  
LOCAL_SRC_FILES := \
  
TransmissionPerson.c     \
  
TransmissionString.c
  
include $(BUILD_SHARED_LIBRARY)

  

老样子,不说了,你懂的。 如果不懂,嘎嘎,那就请点击Android.mk 文件 简介咯

 

       JNI 中间层

      

       TransmissionString.c    // String 传输

     

?
#include <string.h>
#include <jni.h>
#include <android/log.h>
  
JNIEnv* jniEnv;
  
  
//----------------------------------------------------------------
//----------------------------------------------------------------
//----------------------------------------------------------------
  
  
jstring
Java_com_duicky_Transmission_transferString( JNIEnv* env,jobject thiz,jstring msg )
{
     if (jniEnv == NULL) {
         jniEnv = env;
     }
  
     char data[128];
     memset (data, 0, sizeof (data));
     char *c_msg = NULL;
     c_msg = ( char *)(*jniEnv)->GetStringUTFChars(jniEnv, msg, 0);
  
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "C JNI  ---- > %s" ,c_msg);
  
     return (*jniEnv)->NewStringUTF(jniEnv, "This is send by C JNI" );
}

  

 

TransmissionPerson.c // 自定义对象 传输

 

?
#include <string.h>
#include <jni.h>
#include <android/log.h>
  
extern JNIEnv* jniEnv;
  
jclass Person;
jobject mPerson;
jmethodID getName;
jmethodID setName;
jmethodID getAge;
jmethodID setAge;
jmethodID toString;
  
int InitPerson();
void ToString();
void GetName();
void GetAge();
void SetName();
void SetAge();
//----------------------------------------------------------------
//----------------------------------------------------------------
//----------------------------------------------------------------
  
jobject
Java_com_duicky_Transmission_transferPerson( JNIEnv* env,jobject thiz,jobject person )
{
     if (jniEnv == NULL) {
         jniEnv = env;
     }
  
     if (Person == NULL || getName == NULL || setName == NULL || getAge == NULL
             || setAge == NULL || toString == NULL) {
         if (1 != InitPerson()) {
             return NULL;
         }
     }
  
     mPerson =  person;
  
     if (mPerson == NULL) {
         return NULL;
     }
  
     GetName();
     GetAge();
     ToString();
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "Begin Modify mPerson  .... " );
     SetName();
     SetAge();
     ToString();
  
     return mPerson;
}
  
  
//----------------------------------------------------------------
//----------------------------------------------------------------
//----------------------------------------------------------------
  
  
/**
  * 初始化 类、方法
  */
int InitPerson() {
  
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson Begin  " );
  
     if (jniEnv == NULL) {
         return 0;
     }
  
     if (Person == NULL) {
         Person = (*jniEnv)->FindClass(jniEnv, "com/duicky/Person" );
         if (Person == NULL){
             return -1;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson Begin  2 ok" );
     }
  
     if (getName == NULL) {
         getName = (*jniEnv)->GetMethodID(jniEnv, Person, "getName" , "()Ljava/lang/String;" );
         if (getName == NULL) {
             (*jniEnv)->DeleteLocalRef(jniEnv, Person);
             return -2;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson Begin  4 ok" );
     }
  
     if (setName == NULL) {
         setName = (*jniEnv)->GetMethodID(jniEnv, Person, "setName" , "(Ljava/lang/String;)V" );
         if (setName == NULL) {
             (*jniEnv)->DeleteLocalRef(jniEnv, Person);
             (*jniEnv)->DeleteLocalRef(jniEnv, getName);
             return -2;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson Begin  4 ok" );
     }
  
  
     if (getAge == NULL) {
         getAge = (*jniEnv)->GetMethodID(jniEnv, Person, "getAge" , "()I" );
         if (getAge == NULL) {
             (*jniEnv)->DeleteLocalRef(jniEnv, Person);
             (*jniEnv)->DeleteLocalRef(jniEnv, getName);
             (*jniEnv)->DeleteLocalRef(jniEnv, setName);
             return -2;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson Begin  4 ok" );
     }
  
     if (setAge == NULL) {
         setAge = (*jniEnv)->GetMethodID(jniEnv, Person, "setAge" , "(I)V" );
         if (setAge == NULL) {
             (*jniEnv)->DeleteLocalRef(jniEnv, Person);
             (*jniEnv)->DeleteLocalRef(jniEnv, getName);
             (*jniEnv)->DeleteLocalRef(jniEnv, setName);
             (*jniEnv)->DeleteLocalRef(jniEnv, getAge);
             return -2;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson Begin  4 ok" );
     }
  
  
     if (toString == NULL) {
         toString = (*jniEnv)->GetMethodID(jniEnv, Person, "toString" , "()Ljava/lang/String;" );
         if (toString == NULL) {
             (*jniEnv)->DeleteLocalRef(jniEnv, Person);
             (*jniEnv)->DeleteLocalRef(jniEnv, getName);
             (*jniEnv)->DeleteLocalRef(jniEnv, setName);
             (*jniEnv)->DeleteLocalRef(jniEnv, getAge);
             (*jniEnv)->DeleteLocalRef(jniEnv, setAge);
             return -2;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson Begin  4 ok" );
     }
  
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitPerson End" );
     return 1;
}
  
  
  
/**
  * GetName  对应Person的getName方法
  */
void GetName() {
  
     if (Person == NULL || getName == NULL) {
         if (1 != InitPerson()){
             return ;
         }
     }
  
     jstring jstr = NULL;
     char * cstr = NULL;
     //调用方法
     jstr = (*jniEnv)->CallObjectMethod(jniEnv, mPerson, getName);
     cstr = ( char *) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "getName  ---- >  %s" ,cstr );
     //释放资源
     (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
     (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
  
}
  
/**
  * GetAge 对应Person的getName方法
  */
void GetAge() {
  
     if (Person == NULL || getName == NULL) {
         if (1 != InitPerson()){
             return ;
         }
     }
     //调用方法
     jint age = (*jniEnv)->CallIntMethod(jniEnv, mPerson, getAge);
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "getAge  ---- >  %d" ,age );
  
}
  
/**
  * SetName 对应Person的setName方法
  */
void SetName() {
  
     if (Person == NULL || setName == NULL) {
         if (1 != InitPerson()){
             return ;
         }
     }
  
     jstring jstr = (*jniEnv)->NewStringUTF(jniEnv, "Modify Name" );
     //调用方法
     (*jniEnv)->CallVoidMethod(jniEnv, mPerson, setName,jstr);
     (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
  
}
  
int age = 20;
/**
  * SetAge 对应Person的setAge方法
  */
void SetAge() {
  
     if (Person == NULL || setAge == NULL) {
         if (1 != InitPerson()){
             return ;
         }
     }
     //调用方法
     (*jniEnv)->CallVoidMethod(jniEnv, mPerson, setAge,age++);
  
}
  
  
/**
  * ToString 对应 Person 的 toString 方法 , 打印出相关信息
  */
void ToString() {
  
     if (Person == NULL || toString == NULL) {
         if (1 != InitPerson()){
             return ;
         }
     }
  
     jstring jstr = NULL;
     char * cstr = NULL;
     //调用方法
     jstr = (*jniEnv)->CallObjectMethod(jniEnv, mPerson, toString);
     cstr = ( char *) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "C JNI toString  ---- >  %s" ,cstr );
     (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
     (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
  
}

  

3、运行结果

A、测试 String传输 : 点击 第一个按钮,看UI显示 和 LogCat 打印信息

 

<!--[if !supportLists]-->1、  <!--[endif]-->JNI 收到 Java 的信息


<!--[endif]-->

<!--[if !supportLists]-->2、  <!--[endif]-->Java 收到JNI 的信息


<!--[endif]-->

<!--[if !supportLists]-->3、  <!--[endif]-->UI 显示信息


<!--[endif]-->

 

 

 

 

B、测试 自定义对象传输:点击 第二个按钮,看UI显示 和 LogCat 打印信息

1、JNI 收到 Person 对象的 数据(Java 写死了发送 name:duicky ,age:10)

       

 

2、JNI 通过 setName,SetAge改变Person 后的数据


<!--[endif]-->

       3、Java 上层 接收到的数据

       

<!--[if !supportLists]-->4、  <!--[endif]-->UI 显示信息


<!--[endif]-->

 

 

 

以上就是 Java --- JNI  String和 自定义对象 传输的  小例子 , 其他 引用数据类型和Java自定义 都可以仿照上面的做法传输。

 

       还有一种方式 :大数据传输可以通过保存到文件实现。如:上层保存数据到文件然后C JNI 层直接读取文件 或者 C JNI 层保存数据到文件 由 上层读取 。

 

 

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

 

点击下载源码 数据传输二

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值