• Android驱动使用JNI调用


                                             Android驱动使用JNI调用

    学习Android驱动是一个漫长的过程,当然你也可以说有了Linux设备驱动开发经验学习Android驱动是很简单的,呵呵,的却如此,毕竟Android内核是跑在linux内核上,Android的应用调用的其实是linux驱动。Android Application调用Linux驱动可以这么说有两种方法,也就是两种处理的流程。
      Android应用层调用Linux驱动的方式:
      第一,通过在Android内核源码(不是linux内核源码)中添加HAL层、JNI层、开启系统服务,这是一个比较复杂的过程,很多标准的设备都采用这种方式设计,比如说wifi、gps、sensor等,这种调用过程看起来比较标准,但是如果作为第三方开发就会很麻烦,HAL层、JNI层,系统服务层,每层都需要编译Android内核源码,这样就会延长了产品的开发周期;第二,通过配置NDK环境,在NDK环境中直接编写JNI层,然后在Android应用层中添加类,加载JNI库即可调用设备的驱动。
      现在我们以Tiny210上的LED驱动作为例子讲解如何使用NDK环境编写JNI库来调用设备的驱动程序。
      一、首先是编写linux驱动程序,:
    1、源码:linux-2.6.36-android\drivers\char\tiny210_leds.c
    2、修改当前目录(linux-2.6.36-android\drivers\char)的kconfig,添加如下内容:
    config TINY210_LEDS
     tristate "LED Support for Tiny210 GPIO LEDs"
     depends on CPU  S5PV210

     default y
     help
       This option enables support for LEDs connected to GPIO lines
       on Tiny210 boards.
    3、修改当前目录(linux-2.6.36-android\drivers\char)下的makefile文件,添加如下内容:
    obj-$(CONFIG_TINY210_LEDS) += tiny210_leds.o
    4、到源码目录执行make menuconfig 配置LED驱动编译进内核,系统起来就加载驱动
    5、执行 make 生成zImage镜像文件
    二、 重新使用刚刚编译好的zImage烧写Android系统,系统起来以后通过adb查看Android系统加载的驱动程序
    #ls /dev 
    可以看到系统加载的驱动,(leds)
    修改init.rc加载的驱动的读写权限
    chmod 0666 /dev/leds
    这样JNI层才可以打开这个设备
    三、编写JNI文件
    在android工程目录下新建文件jni,然后添加文件ledjni.c,内容如下:
    #include <string.h>
    #include <jni.h>
    #include <fcntl.h>
    #define DEV_NAME "/dev/leds"
    jstring
    Java_com_hellojnipwzh_HardwareControlClass_stringFromJNI( JNIEnv* env,
                                                      jobject thiz )
    {
        return (*env)->NewStringUTF(env, "Hello from JNI !");
    }
    jint
    Java_com_hellojnipwzh_HardwareControlClass_Init(JNIEnv *env,
              jobject thiz)
    {
     int fd=open(DEV_NAME,O_RDWR);
     return fd;
    }
    jint
    Java_com_hellojnipwzh_HardwareControlClass_IOCTLLED(JNIEnv *env,
              jobject thiz,
              jint ledid,
              jint controlcode,
              jint fd)
    {
     int CTLCODE = controlcode;
     ioctl(fd,controlcode,ledid);
     return 0;
    }
    说明:“Java_com_hellojnipwzh_HardwareControlClass_IOCTLLED”,在工程中添加JNI类时,使用com.hellojnipwzh作为packets name,HardwareControlClass这个作为class name  ,IOCTLLED(int id,int code,int fd)作为调用的接口函数,类成员。

    添加脚本Android.mk,内容如下:
    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE    := ledjni
    LOCAL_SRC_FILES := ledjni.c

    include $(BUILD_SHARED_LIBRARY)

    使用Cygwin工具,配置好NDK环境,添加NDK环境到系统变量中,然后进到jni目录,进行
    #ndk-build
    这样就会在android工程的libs目录下的armeabi目录下生成ledjni.so
    这样JNI库已经完成了,接下来就是添加类来调用JNI库
    四、JNI类
    在Android工程中添加一个类,包名:com.hellojnipwzh 类名:HardwareControlClass,具体内容如下:
    package com.hellojnipwzh;

    import android.util.Log;

    public class HardwareControlClass {
     
     static public native String stringFromJNI();
     static public native int Init();
     static public native int IOCTLLED(int ledID, int ledState ,int fd);
     
     static {
         try {
          System.loadLibrary("ledjni");
         } catch (UnsatisfiedLinkError e) {
             Log.d("HardwareControler", "HardwareControler ibrary not found!");
         }
     }
    }
    五、接下来就是在Android应用层代码中通过类来访问驱动了
    package com.hellojnipwzh;

    import android.os.Bundle;
    import android.app.Activity;
    import android.util.Log;
    import android.view.Menu;
    import android.view.View;
    import android.widget.TextView;

    public class HelloJniPwzh extends Activity {

     int fd = -1;
     TextView tv;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_hello_jni_pwzh);

      
      
      fd = HardwareControlClass.Init();
      if (-1 == fd)
       Log.d("JNI", "open device error!");
       
      tv = (TextView)findViewById(R.id.tvid);
      String tstr = "ssss";
      tstr = HardwareControlClass.stringFromJNI();
      tv.setText(tstr);
     }

     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.activity_hello_jni_pwzh, menu);
      return true;
     }
     
     public void onclickLedOn1(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(1, 1, fd);
     }
     public void onclickLedOff1(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(1, 0, fd);
     }
     
     public void onclickLedOn2(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(2, 1, fd);
     }
     public void onclickLedOff2(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(2, 0, fd);
     }
     
     public void onclickLedOn3(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(3, 1, fd);
     }
     public void onclickLedOff3(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(3, 0, fd);
     }
     
     public void onclickLedOn4(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(4, 1, fd);
     }
     public void onclickLedOff4(View v)
     {
      if (fd != -1)
       HardwareControlClass.IOCTLLED(4, 0, fd);
     }

    }
    至此JNI的调用过程也已经完成,接下来就是将Android软件安装到Tiny210上,然后点击下按钮,你就会发现你可以通过Android软件来控制Linux驱动程序了。

  • 相关阅读:
    [ 原创 ] Oracle存储过程中使用游标进行多行数据输出
    [ 原创 ] Python解压版安装配置教程
    [ 转载 ] ORACLE存储过程
    [ 转载 ] Oracle存储过程及函数的练习题
    [ 原创 ] Oracle数据库一些基本命令
    [ 转载 ] Linux CentOS 查看操作系统版本信息
    [ 转载 ] Android开发中如何做单元测试
    [ 转载 ] 关于conn /as sysdba 无需密码直接可以连接的疑问
    [ 转载 ] oracle如何查看当前有哪些用户连接到数据库
    [ 转载 ] Oracle 内存(SGA,PGA)详细介绍
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3037378.html
Copyright © 2020-2023  润新知