• 硬件平台:tiny4412
  • 系统:Android  5.0.2
  • 编译器: arm-linux-gcc-4.5.1

首先来看一下android的系统框图。google后期加入一层HAL层,硬件访问层HAL

https://developer.android.com/guide/platform/index.html


1、android访问硬件驱动的两种方式

android如何管理多个应用对硬件的访问:硬件访问服务。

方法1:

java的JNI技术 使得java可以访问C库。那我们就可以写好一个操作硬件的C库,然后加入到应用的工程中去,通过JNI来访问C库,从而实现对硬件的访问,这是操作硬件最简单的方法,但是没有凸显出android的特色。

优点:传统方法,简单易实现

缺点:jni多个设备同时访问,都可以来open吗?显然效率不好。
技术思路:



方法2:

硬件访问服务:发送请求服务—jni。不同硬件对应不同服务。


2、基于JNI的硬件访问

 2.1、LED应用开发

首先我们来写一个应用程序,这个应用程序主要目的是 实现对硬件LED的操作。

开发框图


编写android应用程序

(1)创建一个android应用程序工程 (2)编写布局代码
<?xml version="1.0" encoding="utf-8"?>        

(3)添加按键和复选框的监听事件: 代码片段:
button.setOnClickListener(new MyButtonListener());
    
class MyButtonListener implements View.OnClickListener {    @Override    public void onClick(View v) {        HardControl hardControl = new HardControl();//依赖硬件        led_on = !led_on;        if (led_on) {            button.setText("ALL OFF");            led1.setChecked(true);            led2.setChecked(true);            led3.setChecked(true);            led4.setChecked(true);            for (int i = 0; i < 4; i++)                HardControl.ledCtrl(i, 1);        }
    
    
android:onClick="onCheckboxClicked"
public void onCheckboxClicked(View view) {    // Is the view now checked?    boolean checked = ((CheckBox) view).isChecked();    // Check which checkbox was clicked    switch(view.getId()) {        case R.id.led1:            if (checked)            {                Toast.makeText(getApplicationContext(),"led1_on",Toast.LENGTH_LONG).show();                HardControl.ledCtrl(1, 1);            }
    else    {        Toast.makeText(getApplicationContext(),"led1_off",Toast.LENGTH_LONG).show();        HardControl.ledCtrl(1, 0);    }    break;case R.id.led2:
(4)申明本地java方法
    

HardControl.JAVA:

package com.example.yangfei.hardlibrary;public class HardControl {    public static native int ledCtrl(int which, int status);    public static native int ledOpen();    public static native void ledClose();//申明三个本地方法。    static {        try {            System.loadLibrary("hardcontrol");        } catch (Exception e) {            e.printStackTrace();        }    }}

下载到单板出错,是因为找不到库


(5)修改build.gradle,告诉系统库在哪里放着

sourceSets {    main {        jniLibs.srcDirs = ['libs']    }}
(6)在app/libs下建armeabi子目录,放入so文件(so怎么得到看下一节JNI文件的编写)

onCreate: HardControl.ledCtrl(0, 1);

2.2 JNI文件编写hardcontrol.c

(1)基本的JNI访问C库实现hardcontrol.c
#include   /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */#include #include #if 0typedef struct {    char *name;          /* Java里调用的函数名 */    char *signature;    /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */    void *fnPtr;          /* C语言实现的本地函数 */} JNINativeMethod;#endifjint ledOpen(JNIEnv *env, jobject cls){return 0;}void ledClose(JNIEnv *env, jobject cls){}jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status){return 0;}static const JNINativeMethod methods[] = {{"ledOpen", "()I", (void *)ledOpen},{"ledClose", "()V", (void *)ledClose},{"ledCtrl", "(II)I", (void *)ledCtrl},};/* System.loadLibrary */JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){JNIEnv *env;jclass cls;if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {return JNI_ERR; /* JNI version not supported */}cls = (*env)->FindClass(env, "com/example/yangfei/hardlibrary/HardControl");if (cls == NULL) {return JNI_ERR;}/* 2. map java hello <-->c c_hello */if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[0])) < 0)return JNI_ERR;return JNI_VERSION_1_4;}
编译hardcontrol.c生成SO文件
arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/  -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so

-I   /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ : jni.h的存放目录


-nostdlib  不使用标准库 是android系统源码里的 如下:

/work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so   : 指定libc.so,因为依赖于这个库



(2)加入打印信息hardcontrol.c

使用:__android_log_print(ANDROID_LOG_DEBUG,"LEDDemo", "native ledOpen ...");











#include   /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */#include #include #include   /* liblog *///__android_log_print(ANDROID_LOG_DEBUG, "JNIDemo", "native add ..."); #if 0typedef struct {    char *name;          /* Java里调用的函数名 */    char *signature;    /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */    void *fnPtr;          /* C语言实现的本地函数 */} JNINativeMethod;#endifjint ledOpen(JNIEnv *env, jobject cls){__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledOpen ...");return 0;}void ledClose(JNIEnv *env, jobject cls){__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledClose ...");}jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status){__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledCtrl : %d, %d", which, status);return 0;}static const JNINativeMethod methods[] = {{"ledOpen", "()I", (void *)ledOpen},{"ledClose", "()V", (void *)ledClose},{"ledCtrl", "(II)I", (void *)ledCtrl},};/* System.loadLibrary */JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){JNIEnv *env;jclass cls;if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {return JNI_ERR; /* JNI version not supported */}cls = (*env)->FindClass(env, "com/thisway/hardlibrary/HardControl");if (cls == NULL) {return JNI_ERR;}/* 2. map java hello <-->c c_hello */if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[0])) < 0)return JNI_ERR;return JNI_VERSION_1_4;}

编译

arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/  -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so -I /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/include /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/liblog.so

(3)hardcontrol.c加入底层控制生成 libhardcontrol.so


#include   /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */#include #include #include #include #include #include #include   /* liblog *///__android_log_print(ANDROID_LOG_DEBUG, "JNIDemo", "native add ...");#if 0typedef struct {    char *name;          /* Java里调用的函数名 */    char *signature;    /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */    void *fnPtr;          /* C语言实现的本地函数 */} JNINativeMethod;#endifstatic jint fd;jint ledOpen(JNIEnv *env, jobject cls){fd = open("/dev/leds", O_RDWR);__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledOpen : %d", fd);if (fd >= 0)return 0;elsereturn -1;}void ledClose(JNIEnv *env, jobject cls){__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledClose ...");close(fd);}jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status){int ret = ioctl(fd, status, which);__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledCtrl : %d, %d, %d", which, status, ret);return ret;}static const JNINativeMethod methods[] = {{"ledOpen", "()I", (void *)ledOpen},{"ledClose", "()V", (void *)ledClose},{"ledCtrl", "(II)I", (void *)ledCtrl},};/* System.loadLibrary */JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){JNIEnv *env;jclass cls;if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {return JNI_ERR; /* JNI version not supported */}cls = (*env)->FindClass(env, "com/example/yangfei/hardlibrary/HardControl");if (cls == NULL) {return JNI_ERR;}/* 2. map java hello <-->c c_hello */if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[0])) < 0)return JNI_ERR;return JNI_VERSION_1_4;}
编译:
arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/  -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so -I /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/include /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/liblog.so

2.3 编写驱动程序leds_4412.c

(驱动编译进linux内核,并创建设备节点)

(1)驱动程序编写

应用程序的不会看原理图,只会用open read write。

参考内核中的厂家驱动代码:





#include #include #include #include #include #include #include #include #include #include #include  #include #include #include static int led_gpios[] = {EXYNOS4212_GPM4(0),EXYNOS4212_GPM4(1),EXYNOS4212_GPM4(2),EXYNOS4212_GPM4(3),};static int led_open(struct inode *inode, struct file *file){/* 配置GPIO为输出引脚 */int i;for (i = 0; i < 4; i++)s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);return 0;}/* app : ioctl(fd, cmd, arg) */static long led_ioctl(struct file *filp, unsigned int cmd,unsigned long arg){/* 根据传入的参数设置GPIO *//* cmd : 0-off, 1-on *//* arg : 0-3, which led */if ((cmd != 0) && (cmd != 1))return -EINVAL;if (arg > 4)return -EINVAL;gpio_set_value(led_gpios[arg], !cmd);return 0;}static struct file_operations leds_ops = {/* 结构 */    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */    .open   =   led_open,     .unlocked_ioctl= led_ioctl,};static int major;static struct class *cls;int leds_init(void)/* 入口函数 */{major = register_chrdev(0, "leds", &leds_ops);/* 为了让系统udev,mdev给我们创建设备节点 *//* 创建类, 在类下创建设备 : /sys */cls = class_create(THIS_MODULE, "leds");device_create(cls, NULL, MKDEV(major, 0), NULL, "leds"); /* /dev/leds */return 0;}void leds_exit(void)/* 出口函数 */{device_destroy(cls, MKDEV(major, 0));class_destroy(cls);unregister_chrdev(major, "leds");}module_init(leds_init);module_exit(leds_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("www.100ask.net");
(2)编译驱动程序

leds_4412.c放入内核 drivers/char

修改drivers/char/Makefile,添加:

obj-y += leds_4412.o

重新编译内核

make zImage

work/linux-3.0.86/arch/boot/zImage

下载内核到开发板



Cat /proc/devices



3、总结

(1)写了一个java类,通过 System.loadLibrary("hardcontrol");来加载本地C库。 (2)在app/libs下建armeabi子目录,放入so文件。 需要制定lib库的位置
sourceSets {    main {        jniLibs.srcDirs = ['libs']    }}
编译c库:
(3)-I   /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ : jni.h的存放目录 (4) -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so   :指定libc.so, 不使用标准库libc.so.6   libc.so是android系统源码里有的, 使用这个这个库 增加android打印: (5)打印信息: __android_log_print(ANDROID_LOG_DEBUG,"LEDDemo", "native ledOpen ..."); 需要加入头#include
(6)   指定liblog.so库路径   /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/liblog.so

启动应用 测试程序


APP,JNI,驱动代码下载地址:

点击打开链接

http://download.csdn.net/detail/fengyuwuzu0519/9755859

更多相关文章

  1. 箭头函数的基础使用
  2. Python技巧匿名函数、回调函数和高阶函数
  3. Android(安卓)- ListActivity 单击事件的响应
  4. android WebView总结
  5. Android(安卓)利用JNI调用Android(安卓)Java代码函数
  6. 如何修改Android的Bitmap
  7. Android(安卓)框架层为IMountService 增加新接口
  8. QT for Android(安卓)HelloWorld实现
  9. ActivityThread 源码笔记(1)

随机推荐

  1. Android(安卓)Instrumentation Testing
  2. Android在中国的发展分析
  3. Android音频开发(1):基础知识
  4. 如何在Android和iOS设备上录制游戏?
  5. Android状态栏黑色字体
  6. Android菜单详解(一)——理解android中的Me
  7. Android系统框架和几种调用流程
  8. Android(安卓)亮度调节
  9. Android上的C/C++调用Java问题(转载)
  10. Android性能监测:Looper机制监测卡顿和丢