接著上篇文章繼續講。主要關於參考型別的資料轉送,本文將介紹字串傳輸和自訂對象的傳輸。
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 部落格