基於Android NDK的學習之旅—–數據傳輸二(引用數據類型) – Android移動開發技術文章_手機開發 Android移動開發教學課程

  接著上篇文章繼續講。主要關於引用類型的數據傳輸,本文將介紹字符串傳輸和自定義對象的傳輸。

 

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 上層:

view plain
public nativeString transferString(String mStrMSG); 
public nativeObject  transferPerson(Person mPerson);       
 
Person.java

view plain
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 文件

     

view plain
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 傳輸

    

view plain
#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 // 自定義對象 傳輸

 

view plain
#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 博客

發佈留言