標籤:
繼上一篇,我們在native介面中編寫了2個方法
產生的相應.h檔案
這時,需要我們自己去完善.c檔案
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Header for class led_oki_com_jnidemo_AppJNI */
#ifndef _Included_led_oki_com_jnidemo_AppJNI
#define _Included_led_oki_com_jnidemo_AppJNI
#ifdef __cplusplus
extern "C" {
#endif
這段可不變,固定
#include "android/log.h"
#define TAG "jnidemo-jni-test" // 這個是自訂的LOG的標識
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__) // 定義LOGD類型
這段主要是自訂的LOG標識,相當於Android中的LOG.D()方法
方法一:getStringFromNative
JNIEXPORT jstring JNICALL Java_com_oki_led_jni_AppJNI_getStringFromNative
(JNIEnv * env, jobject jObj){
LOGD("log string from ndk.");
return env->NewStringUTF(env,"Hello From JNI!");
}
這段,對應我們的native寫的方法之一getStringFromNative,自訂的LOG使用則是使用自訂的方法名LOGD("提示內容")
這個方法意思是返回一個String類型的資料,資料是Hello From JNI!
在Android裡就可以接收到這段String
AppJNI appJNI = new AppJNI();
String msg = appJNI.getStringFromNative();
這時,msg接收的資料就是Hello From JNI!
方法二:doCoordTest(COORD coord)
JNIEXPORT jobject JNICALL Java_com_oki_led_jni_AppJNI_doCoordTest
(JNIEnv *env, jobject obj, jobject coord) {
jclass coordClass = (*env)->GetObjectClass(env, coord);
if( coordClass){
jboolean iscopy;
jfieldID xId = (*env)->GetFieldID(env, coordClass, "x", "I");
jint x = (int)(*env)->GetIntField(env, coord, xId);
LOGD("x = %d", x);
jfieldID yId = (*env)->GetFieldID(env, coordClass, "y", "I");
jint y = (int)(*env)->GetIntField(env, coord, yId);
LOGD("y = %d", y);
jfieldID widthId = (*env)->GetFieldID(env, coordClass, "width", "I");
jint width = (int)(*env)->GetIntField(env, coord, widthId);
LOGD("width = %d", width);
jfieldID heightId = (*env)->GetFieldID(env, coordClass, "height", "I");
jint height = (int)(*env)->GetIntField(env, coord, heightId);
LOGD("height = %d", height);
}
jclass cls = (*env)->FindClass(env, "com/oki/led/jni/nativeobj/COORD");
jmethodID id = (*env)->GetMethodID(env, cls, "<init>", "()V");
jobject paramOut = (*env)->NewObjectA(env, cls, id, 0);
return paramOut;
}
其中,COORD是在Android中建立的一個COORD對象類
public class COORD {
public int x;
public int y;
public int width;
public int height;
/**
* 設定初始值
* 為什麼要設定初始值:防止在執行c檔案中,資料出錯或內容溢出等不必要的問題,也減少在c檔案中對資料的判斷,懶人方法(可用可不用)
*/
public COORD() {
x = 0;
y = 0;
width = 0;
height = 0;
}
}
如果native中設定的傳遞一個類,那麼c檔案中,一開始接收的資料應該是jobject類型,通過jobject類型轉換成jclass類型,再取出class類中各個數值
jclass coordClass = (*env)->GetObjectClass(env, coord);
片段1:取值
//取類中的數值 x ID
jfieldID xId = (*env)->GetFieldID(env, coordClass, "x", "I");
//將 x ID 轉換成相應類型的 x 數值
jint x = (int)(*env)->GetIntField(env, coord, xId);
//列印 x 資料,用於在Android運行過程中,判斷該數值是否正確
LOGD("x = %d", x);
片段2:調用初始方法
//尋找class 類 COORD
jclass cls = (*env)->FindClass(env, "com/oki/led/jni/nativeobj/COORD");
//對該類調用其初始化方法
jmethodID id = (*env)->GetMethodID(env, cls, "<init>", "()V");
//將cls類中的資料再轉成jobject類
jobject paramOut = (*env)->NewObjectA(env, cls, id, 0);
//將資料返回出去
return paramOut;
片段3:賦值
如果需要將片段1中的取值內容返回出去,需要再新建立一個jobject方法承載這些資料
//尋找class 類 COORD
jclass cls = (*env)->FindClass(env, "com/oki/led/jni/nativeobj/COORD");
//可要可不要
jmethodID id = (*env)->GetMethodID(env, cls, "<init>", "()V");
//將cls類中的資料再轉成jobject類
jobject paramOut = (*env)->NewObjectA(env, cls, id, 0);
jfieldID xId = (*env)->GetFieldID(env, coordClass, "x", "I");
//將xId賦值為3
(*env)->SetIntField(env, paramOut, xId, 3);
return paramOut;
基本上就是這樣,遺留問題:賦值是否有更方便的方法?裡面是否有一些代碼重複?
Android Studio中JNI -- 2 -- 編寫c檔案