Android Studio中JNI -- 2 -- 编写c文件

继上一篇,我们在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;

基本上就是这样,遗留问题:赋值是否有更方便的方法?里面是否有一些代码重复?

 

posted @ 2016-01-21 11:50  QqiaoQ  阅读(316)  评论(0编辑  收藏  举报