• 硬件平台: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基础学习--->Android(安卓)Shared
  2. Android SQLiteOpenHelper Sqlite数据库
  3. Mac下关于The "android" command is depr
  4. android RSA和Java RSA加密不一致的坑
  5. android配置X86虚拟机
  6. Android数字跑动效果NumberRunView 类似
  7. 睡眠唤醒机制简介
  8. 禁止android显示状态栏
  9. Android兼容android7.0、及Android8.0以
  10. android could not find adb.exe 如何解