原文网址: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 <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 打印信息

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 层保存数据到文件 由 上层读取 。

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

点击下载源码 数据传输二

本文出自 duicky博客 , 转载请注明出处

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

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

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

    接着上篇文章继续讲.主要关于引用类型的数据传输,本文将介绍字符串传输和自定义对象的传输. 1.主要流程 1.  String 字符串传输 a)         上层定义一个native的方法,需要一个 ...

  2. 基于 Android NDK 的学习之旅-----环境搭建

    工欲善其事 必先利其器 , 下面介绍下 Eclipse SDK NDK Cygwin CDT 集成开发环境的搭建. 1.Android 开发环境搭建 Android开发环境搭建不是重点,相信看此文章的 ...

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

    前些日子做了个Android项目, 引擎层 用C的, 准备写这个系类的文章,借此跟朋友来分享下我NDK开放的经验以及自己知识的总结和备忘.希望能给需要这方面资料的朋友提供一定的帮助. 主要涉及到:   ...

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

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

  5. 基于 Android NDK 的学习之旅-----HelloWorld

    Hello World作为所有编程语言的起始阶段,占据着无法改变的地位,所有中/英/法/德/美……版本的编程教材中,hello world总是作为第一个TEST记录于书本之中,所有的编程第一步就在于此 ...

  6. 基于 Android NDK 的学习之旅-----JNI LOG 打印

    程序都是调出来的. 下面我介绍下JNI层的log打印方法的使用,类似与Android sdk提供的log 1.Android 应用层 MainActivity.java 主要功能代码 a)       ...

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

    随便谈谈为什么要Java调用C 吧: 我认为: 1.  有些公司开发Android项目的时候, 许多组件功能可能是C中已经实现了,所以我们没必要同样的功能又在java中实现一遍.例如我之前做的一个项目 ...

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

    许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现. 下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态 ...

  9. 基于 Android NDK 的学习之旅-----Android.mk 介绍

    一个Android.mk file用来向编译系统描述你的源代码.具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次.你可以在每一个Android.mk file中定义一个 ...

随机推荐

  1. asp.net mvc 实现记忆返回的功能

    大体思路是在当前跳转链接追加一个参数memoryguid,以guid为key把查询query保存在cookie里,跳转的时候带走这个guid,回来的时候还带着,这样我们就能根据这个guid从cooki ...

  2. C++ 简单的入门语法

    入门的hello world using namespace std; 是使用命名空间,有点像java里面的引入包main 方法和java一样是主入口,有且只有一个,因为是int ,所以还必须返回一个 ...

  3. Activity.startManagingCursor方法

    http://blog.sina.com.cn/s/blog_6f14deb60100wd2n.html 总结一下Activity.startManagingCursor方法: 转 我们将获得的Cur ...

  4. iOS Instruments之Core Animation动画性能调优(工具复选框选项介绍)

    Core Animation工具用来监测Core Animation性能.它给我们提供了周期性的FPS,并且考虑到了发生在程序之外的动画(见图12.4) Core Animation工具提供了一系列复 ...

  5. What is SaaS?

    SaaS, or Software as a Service, describes any cloud service where consumers are able to access softw ...

  6. 《service》-“linux命令五分钟系列”之二

    本原创文章属于<Linux大棚>博客. 博客地址为http://roclinux.cn. 文章作者为roc 希望您能通过捐款的方式支持Linux大棚博客的运行和发展.请见“关于捐款” == ...

  7. ZOJ 3872 Beauty of Array

    /** Author: Oliver ProblemId: ZOJ 3872 Beauty of Array */ /* 需求: 求beauty sum,所谓的beauty要求如下: 1·给你一个集合 ...

  8. Html5的<button>标签

    1.标签是双标签,其内可添加文字,图片等复杂的样式. ​2.不仅可以在表单中使用,还可以在其他块元素和内联元素中使用. 3.一般在input标签内添加name属性,否则提交后不显示.

  9. 一站式远程页面调试工具spy-debugger 2.0,已支持HTTPS

    项目名称: spy-debugger 项目地址:https://github.com/wuchangming/spy-debugger 关于spy-debugger npm Build Status ...

  10. QQ弹窗代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...