开发板:TQ210
OS:Android 4.0.3
以下所有内容都是在TQ210开发板上实现,并且很多内容也是天嵌公司提供,我将一些内容进行了删减、替换,然后加入了一些自己的理解,同时也是记录自己学习的旅程。
led_unders_led_jni.c
#include <jni.h> //包含jint JNINativeMethod... #include <android/log.h> //包含__android_log_print... #include <hardware/led_unders_led_hal.h> #include <hardware/hardware.h> #include <stdio.h> #define false 0 #define true 1 #ifdef __cpulspuls extern "C" { //使用C语言的方式进行编译和连接 #endif static struct led_control_device_t *ledundersdevice=NULL; //led设备指针 static inline int led_control_open(struct hw_module_t *module,struct led_control_device_t **device) { //通过module的open方法找到device,并赋值给ledunderdevice int err=module->methods->open(module,LED_UNDERS_HARDWARE_MODULE_ID,(struct hw_device_t **)device); __android_log_print(ANDROID_LOG_DEBUG,"msg","led_control_open ,err=%d",err); return err; } static jboolean led_close(JNIEnv *env,jclass clazz) //关闭设备 { if(ledundersdevice) //关闭设备 ledundersdevice->common.close(&(ledundersdevice->common)); return 0; } static jboolean led_setOn(JNIEnv *env,jclass clazz,jint number) //打开led { if(ledundersdevice) return ledundersdevice->led_on(ledundersdevice,number); return false; } static jboolean led_setOff(JNIEnv *env,jclass clazz,jint number) //关闭led { if(ledundersdevice) return ledundersdevice->led_off(ledundersdevice,number); return false; } static jboolean led_init(JNIEnv *env,jclass clazz) //初始化本地函数 { struct led_module_t *module; //通过ID查找到模块 int err=hw_get_module(LED_UNDERS_HARDWARE_MODULE_ID, (const hw_module_t **) &module); if(err==0) { //通过module的common成员,找到设备指针并赋给ledunderdevice if(led_control_open(&(module->common),&ledundersdevice)==0) return true; } ledundersdevice=NULL; __android_log_print(ANDROID_LOG_DEBUG,"msg","led_init failed.\n"); return false; } static JNINativeMethod methods[]= //方法数组 { {"led_init","()Z",(void *)led_init}, {"led_setOn","(I)Z",(void *)led_setOn}, {"led_setOff","(I)Z",(void *)led_setOff}, {"led_close","()Z",(void *)led_close}, }; jint register_native_led_method(JNIEnv *env) //注册本地方法 { static char *className="com/unders/led/LedUnderActivity"; //对应于上层应用的类的完整路径 jclass clazz; clazz=(*env)->FindClass(env, className); //Returns a class object from a fully-qualified name, or NULL if the class cannot be found. if(clazz==NULL) { __android_log_print(ANDROID_LOG_DEBUG,"msg","can not find class %s",className); return -1; } if((*env)->RegisterNatives(env,clazz,methods, sizeof(methods)/sizeof(methods[0]))!=JNI_OK) { __android_log_print(ANDROID_LOG_DEBUG,"msg","can not register native.\n"); return -1; } return 0; } jint JNI_OnLoad(JavaVM * vm, void * reserved) //加载库时,第一个调用的函数 { JNIEnv *env=NULL; //JNI函数的接口指针 pointer to the location where the JNI interface pointer for the current thread will be placed. jint result=-1; if((*vm)->GetEnv(vm,(void **)&env,JNI_VERSION_1_4)!=JNI_OK) //判断JNI_VERSION_1_4这个版本是否支持 { __android_log_print(ANDROID_LOG_DEBUG,"msg","JNI_VERSION_1_4 not supported.\n"); return result; } if(register_native_led_method(env)!=0) //注册本地方法 { __android_log_print(ANDROID_LOG_DEBUG,"msg","register native failed.\n"); return result; } return JNI_VERSION_1_4; } #ifdef __cpulspuls } #endif
Android.mk
LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE :=false LOCAL_SRC_FILES :=led_unders_led_jni.c LOCAL_SHARED_LIBRARIES :=libutils \ libhardware LOCAL_MODULE :=libledunders LOCAL_MODULE_TAGS :=optional LOCAL_MODULE_PATH :=$(LOCAL_PATH) include $(BUILD_SHARED_LIBRARY)
Oracle JNI的官网 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html
在写JNI之前最好去上面的官网上 看看JNI的一些基本概念 比如JNI的接口函数、Invocation API。。。
对于JNI,个人的理解,上层APK通过JNI访问HAL提供的接口,从而操纵驱动程序,驱动硬件。
附:生成的libledunders.so文件放在/system/lib/目录下 apk在装载so文件时 会从该目录下查找匹配的