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

原文网址:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/20/2147086.html

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

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

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

1、主要流程

1、  String 字符串传输

a)         上层定义一个native的方法,需要一个String  参数 ,返回一个String

b)        JNI对应上层的方法,打印出上层传输下来的String数据,并返回处理String数据

c)         上层 收到 native 方法 返回的 值,在UI中显示出来

2、  自定义对象的传输

a)         自定义一个对象Person

b)        上层定义一个native方法,参数Person,返回值Person

c)         JNI接收对象,打印出相关信息数据

d)        JNI 修改Person 对象数据,并返回到上层

e)         上层接收到数据后 在UI显示出来

2设计实现

1、  界面设计如下:

老老样子,很搓,嘿嘿

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

2、  关键代码说明

Java 上层:

public native String transferString(String mStrMSG);

public native Object  transferPerson(Person mPerson);     

  

Person.java

package com.duicky;

/**

 *

 *

 * @author luxiaofeng <[email protected]>

 *

 */

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 打印信息

1、  JNI 收到 Java 的信息

2、  Java 收到JNI 的信息

3、  UI 显示信息

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

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

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

3、Java 上层 接收到的数据

4、  UI 显示信息

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

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

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

点击下载源码 数据传输二

http://www.cnblogs.com/luxiaofeng54/archive/2011/08/20/2147086.html

时间: 2024-10-09 23:15:28

【转】基于 Android NDK 的学习之旅-----数据传输(引用数据类型)的相关文章

基于 Android NDK 的学习之旅-----序言

http://www.cnblogs.com/luxiaofeng54/tag/android/default.html?page=1 基于 Android NDK 的学习之旅-----目录 duicky 2011-09-15 16:34 阅读:3035 评论:2 基于 Android NDK 的学习之旅-----资源释放 duicky 2011-08-21 14:29 阅读:6173 评论:0 基于 Android NDK 的学习之旅-----数据传输二(引用数据类型)(附源码) duicky

基于 Android NDK 的学习之旅----- C调用Java

http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html 基于 Android NDK 的学习之旅----- C调用Java许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现. 下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态方法. 1.主要流程 1.  新建一个测试类TestProvider.java a)       

Android热修复学习之旅——HotFix完全解析

在上一篇博客Android热修复学习之旅开篇--热修复概述中,简单介绍了各个热修复框架的原理,本篇博客我将详细分析QQ空间热修复方案. Android dex分包原理介绍 QQ空间热修复方案基于Android dex分包基础之上,简单概述android dex分包的原理就是:就是把多个dex文件塞入到app的classloader之中,但是android dex拆包方案中的类是没有重复的,如果classes.dex和classes1.dex中有重复的类,当classes.dex和classes1

android NDK 实用学习-java端对象成员赋值和获取对象成员值

1,关于java端类及接口定义请参考: android NDK 实用学习-获取java端类及其类变量 2,对传过来的参数进行赋值: 对bool类型成员进行赋值  env->SetBooleanField(jobj, jfbdata, false); 对double类型成员进行赋值 env->SetDoubleField(jobj, jfddata, 209.22); 对int类型成员进行赋值 env->SetIntField(jobj, jfidata, 3653); 对byte类型成员

android NDK 实用学习(三)- java端类对象的构造及使用

1,读此文章前我假设你已经读过: android NDK 实用学习-获取java端类及其类变量 android NDK 实用学习-java端对象成员赋值和获取对象成员值 2,java端类对象的构造: ①首先获取类; ②获取类的无参构造函数: jmethodID initID = env->GetMethodID(jcSetDataMgr, "<init>", "()V"); ③构造类实例: jobject jresult = env->New

android NDK 实用学习(五)-c++端调用java接口

1,阅读此文章前请阅读前面文章,以免阅读出现障碍: android NDK 实用学习(一)-获取java端类及其类变量 android NDK 实用学习(二)-java端对象成员赋值和获取对象成员值 android NDK 实用学习(三)- java端类对象的构造及使用 android NDK 实用学习(四)-类缓存 2,java端类接口定义: 1 public class RTKNativeManager { 2 // 其他接口 3 4 // 开给c++端的接口 5 public static

android NDK 实用学习-获取java端类及其类变量

近期为android 端项目包装一些c++代码,故学习ndk相关知识,现总结如下: 1,java与c++类型参照图: 2,此测试中使用的java类: 1 package com.dasea.test.core; 2 public class TestSetData { 3 // 主要是类ID和字段ID,方法ID的缓存 4 static { 5 OnNative(); 6 } 7 8 public native static void OnNative(); 9 10 public boolean

Android计时器Chronometer-android学习之旅(二十一)

Chronometer简介 Chronometer和DigitalColok都继承与TextView,但是Chronometer不是显示的当前时间,而是从某个时间开始又过去了多少时间,是一个时间差. Chronometer的属性 记时20秒的实例 package peng.liu.testview; import android.app.Activity; import android.os.Bundle; import android.os.SystemClock; import androi

Android对话框AlertDialog-android学习之旅(四十二)

对话框简介 android提供了丰富的对话框支持,支持四种如下的对话框. AlertDialog简介 介绍上面六个方法的代码示例 setMessage() <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://s