JNI 的基本内容
- 理解JNI的作用
a java native interface ( 提供调用本地方法的接口)
b java 调用c/c++ 时是通过jni层间接调用
c jni的技术是在vm中实现
d java <----> c 数据间的转换
java通过参数把数据传给c,c通过返回值把数据给到java。
e 整型 int == jint, 字符 2c == java
f java字符串转为c字符串
char *temp = env->GetStringUTF(str,NULL);
g c字符串转为java字符串
jstring jtemp = env->NewStringUTFChars("hello word");
env->ReleasestringUTFchars(str,jtemp);
- JNI的编程
1. 编写app:
static{ //优先执行
System.loadLibrary("led_jni"); // /system/lib/libled_jni.so
}
//声明本地方法--自定义
native int openDev();
native int devOn();
native int devOff();.
native int closeDev();
- myjni.cpp
说明:
实例– development/samples/SimpleJNI
注意– 用source insight写,并添加android源码。
a //jni代码的入口
jint JNI_OnLoad(JavaVM * vm,void * reserved)
{
//正常返回JNI_VERSION_1_4, 错误返回负数
return JNI_VERSION_1_4;
}
b 从vm中获取到环境变量对象,包含了大量的方法
int GetEnv(void * * env,jint version);
参数1:获取的环境变量对象
参数2:测试jni的版本:JNI_VERSION_1_4
返回值:正确返回0, 错误负数
JNIEnv *env = NULL;
jint ret;
ret = vm->GetEnv((void * * )&env, JNI_VERSION_1_4);
if(ret != 0)
{
LOGE("vm->GetEnv error");
return -1;
}
c java代码中的本地方法包
jclass mycls = env->FindClass("com/hq/ledcontroltest/LedNative");
if(mycls == NULL)
{
LOGE("env->FindClass error");
return -1;
}
d 实现映射表的功能
//表示一个映射表:
typedef struct {
const char* name; // java的方法名
const char* signature; //java的方法的描述
void* fnPtr; // c/c++的函数名
} JNINativeMethod;
JNINativeMethod myMethods[] = {
{"openDev", "()I", (void *)open_led},
{"devOn", "()I", (void *)led_on},
{"devOff", "()I", (void *)led_off},
{"closeDev", "()I", (void *)close_led},
};
e 注册映射表
参数1:给出java中本地方法所在的包,类路径
参数2: 映射表
参数3: 数组中元素的个数
ret = env->RegisterNatives(mycls, led_Methods,
sizeof(led_Methods)/sizeof(led_Methods[0]));
if(ret < 0)
{
LOGE("env->RegisterNatives error");
return -1;
}
f 实现映射表的方法
jint open_led(JNIEnv *env, jobject thiz){
}
jint led_on(JNIEnv *env, jobject thiz){
}
jint led_off(JNIEnv *env, jobject thiz){
}
jint close_led(JNIEnv *env, jobject thiz){
}
没有HAL层
android.mk (mmm xxx.cpp 编译jni)
#获取当前路径
LOCAL_PATH:= $(call my-dir)
#清空以LOCAL_XX的变量,除了LOCAL_PATH
include $(CLEAR_VARS)
#在任何情况都会编译
LOCAL_MODULE_TAGS := optional
#依赖--指定源码
LOCAL_SRC_FILES:= myled_jni.cpp
#依赖动态库(-lpthread)
LOCAL_SHARED_LIBRARIES := \
libcutils
#目标--指定目标文件名
LOCAL_MODULE:= libled_jni
#添加自定义的头文件
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
#编译规则---编译成可执行程序
include $(BUILD_SHARED_LIBRARY)
myjni.cpp
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define LOG_TAG "LED_JNI_LOG"
#include <utils/Log.h>
#include "jni.h"
static int fd ;
jint open_led(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
fd = open("/dev/led1", O_RDWR);
if(fd < 0)
{
LOGE("open : %s\n", strerror(errno));
return -1;
}
return 0;
}
jint led_on(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
jint on = 1;
jint ret;
ret = write(fd, &on, 4);
if(ret < 0)
{
LOGE("write on : %s\n", strerror(errno));
return -1;
}
return 0;
}
jint led_off(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
jint on = 0;
jint ret;
ret = write(fd, &on, 4);
if(ret < 0)
{
LOGE("write on : %s\n", strerror(errno));
return -1;
}
return 0;
}
jint close_led(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
close(fd);
return 0;
}
const JNINativeMethod led_Methods[] = {
{"openDev", "()I", (void *)open_led},
{"devOn", "()I", (void *)led_on},
{"devOff", "()I", (void *)led_off},
{"closeDev", "()I", (void *)close_led},
};
jint JNI_OnLoad(JavaVM * vm,void * reserved)
{
JNIEnv *env = NULL;
jint ret;
ret = vm->GetEnv((void * * )&env, JNI_VERSION_1_4);
if(ret != JNI_OK)
{
LOGE("vm->GetEnv error");
return -1;
}
jclass mycls = env->FindClass("com/hq/ledcontroltest/LedNative");
if(mycls == NULL)
{
LOGE("env->FindClass error");
return -1;
}
ret = env->RegisterNatives(mycls, led_Methods,
sizeof(led_Methods)/sizeof(led_Methods[0]));
if(ret < 0)
{
LOGE("env->RegisterNatives error");
return -1;
}
//正常返回JNI_VERSION_1_4, 错误返回负数
return JNI_VERSION_1_4;
}
有HAL层
//添加以下内容
#include "led_hal.h"
//定义两个指针
struct led_hw_module_t *pModule;
struct led_hw_device_t *pDevice;
jint open_led(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
jint ret;
ret = hw_get_module(LED_MODULE_ID,(const struct hw_module_t * * )&pModule);
if(ret == 0)
{
LOGD("hw_get_module ok\n");
if(pModule != NULL)
{
//调用hal中的module的open方法
pModule->common.methods->open(&pModule->common, NULL,
(struct hw_device_t** )&pDevice);
//如果调用成功pDevice会被初始化
if(pDevice != NULL)
pDevice->open();
}
}else{
LOGE("hw_get_module error\n");
}
return 0;
}
//实现的方法修改为以下
jint led_on(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
if(pDevice != NULL)
pDevice->control_dev(1);
return 0;
}
jint led_off(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
if(pDevice != NULL)
pDevice->control_dev(0);
return 0;
}
jint close_led(JNIEnv *env, jobject thiz)
{
LOGD("---------%s-----------\n", __FUNCTION__);
if(pDevice != NULL)
pDevice->common.close((struct hw_device_t* )pDevice);
return 0;
}