博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【转】Android通过JNI调用驱动程序(完全解析实例)
阅读量:5296 次
发布时间:2019-06-14

本文共 7340 字,大约阅读时间需要 24 分钟。

原文网址:http://blog.csdn.net/ok138ok/article/details/6560875

 要达到的目的:android系统中,用JAVA写界面程序,调用jni中间库提供的接口,去操作某个驱动节点,实现read,writer ioctl等操作!这对底层驱动开发人员是很重要的一个调试通道,也是android 系统下提供一些特殊功能接口的方法!

本文前提:我们假设已经写了一个驱动程序,它是控制LED的亮灭的,并且创建了一个节点:/dev/vib,也就是通过open这个vib节点,可以read/write/ioctl 操作驱动程序实现LED灯的亮灭控制,具体可以看我另一篇博文《

开发环境 1、ubuntu下的NDK编译环境,2、Esclips开发环境

一、编写JNI模块

当安装好NDK编译环境后,会在它的目录下找到sample目录,它里面有一些例子,可以参考这些例子来写我们自已的模块。

clip_image002

1、 source文件夹下,新建“LEDSJNI”文件夹。

2、 Source/LEDSJNI/jni/目录下,新建“vib-jni.c”

vib-jni.c文件

 

#include 
#include
#include
/*包括文件操作,如open() read() close() write()等*/ //----for output the debug log message #include
#define LOG_TAG "vib-jni" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #define DEVICE_NAME "/dev/vib" //device point #define VIB_ON 0x11 #define VIB_OFF 0x22 int fd; jstring Java_com_auly_control_vibClass_stringFromJNI( JNIEnv* env, jobject thiz ) {
return (*env)->NewStringUTF(env, "Hello from JNI--Peter for vib!");//打印字符串 } jint Java_com_auly_control_vibClass_Init( JNIEnv* env ) {
LOGE("vibClass_Init() /n"); fd = open(DEVICE_NAME,O_RDWR);//打开设备 LOGE("vibClass_Init()-> fd = %d /n",fd); if(fd == -1) {
LOGE("open device %s error /n ",DEVICE_NAME);//打印调试信息 return 0; } else {
return 1; } } jint Java_com_auly_control_vibClass_IOCTLVIB( JNIEnv* env, jobject thiz, jint controlcode ) {
int CTLCODE = controlcode; LOGE("IOCTLVIB() = %x --vibClass_IOCTLVIB /n",CTLCODE); switch(CTLCODE) {
case VIB_ON: {
ioctl(fd,VIB_ON);//调用驱动程序中的ioctrl接口,把命令VIB_ON传下去,实现硬件操作 break; } case VIB_OFF: {
ioctl(fd,VIB_OFF);//调用驱动程序中的ioctrl接口,把命令VIB_OFF传下去,实现硬件操作 break; } default:break; } return 1; }

 

 

3、相同目录下的新建Android.mk如下

Android.mk文件

 

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE    := vib-jni LOCAL_SRC_FILES := vib-jni.c LOCAL_CFLAGS    := -Werror LOCAL_LDLIBS    := -llog -lGLESv2 //__android_log_print 函数 include $(BUILD_SHARED_LIBRARY)

 

可以看到,主要是修改LOCAL_SRC_FILES指向源文件的名称!

还有一点很重要,如果要使用调试LOG 打印,也就是__android_log_print 函数。要在LOCAL_LDLIBS中添加-llog,如上面的Android.mk所示。

4、编译JNI模块

#cd /home/workspace/android-ndk-r4b/sources/LEDSJNI

进到刚才写的JNI目录

 

#ndk-build

编译JNI,编译成功后,会在LEDSJNI文件夹下生成libs和obj两个文件夹,并在

LEDSJNI/libs/armeabi下得到目标文件libvib-jni.so

clip_image002[8]

(目前LEDSJNI文件夹只有3个目录jni,libs,obj)

二、JAVA程序

1、Eclipse新建工程

拷贝LEDSJNI目录到Windows下,例如C盘下。然后在它里面新建Eclipse 工程。

clip_image002[10]
clip_image004

新键工程后,

如果出现如下错误:

ERROR: Unable to open class file C:/LEDSJNI/gen/com/auly/control/R.java: No such file or directory

解决方法如下:

对着该工程鼠标右键 》bulid path 》configure build path》java build path》order and Export

 

clip_image002[12]

把里面的android 2.1勾上,Build project,就OK了

clip_image002[14]

然后 Run as > Android application,就会出现android的模拟器了,里面跑个helloworld出来。

clip_image002[16]

2、加入button和文本输出

程序到上面为止代码是ADT自动生成的,似乎与我们一点关系也没有。那我们来改一下代码,因为我们调用JNI接口是为了访问驱动程序操作硬件的,例如写,读,打开LED,关闭LED等等,由按钮触发的动作。

第一步是,增加两个Button,,在main.xml里描述一下:打开Res > layout> main.xml 文件

 

rientation="vertical"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     > 

 

 

实际代码中,把注释去掉,否则编译不过的。

3、加入输出字符串资源

工程 > values > strings.xml 文件

clip_image002[18]
修改如下
Led 控制程序
LEDAPP
打开LED
关闭LED

上面的”打开LED”等资源,就是用在按钮上显示出来的字符串

经过上面的修改,现在程序界面上,已经有如下效果了

鼠标右键工程名>Run as > Android application 运行程序。

clip_image004[11]

4、加入按钮对应的动作

“打开LED”按扭:调用JNI的IOCTLVIB(VIB_ON);

“关闭LED”按钮:调用JNI的 IOCTLVIB(VIB_OFF);

操作:

在LEDAPP > src > com.auly.control > vibrator.java文件

 

package com.auly.control; /**定义头文件*/ import android.widget.TextView; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.util.Log; import android.app.Activity; import android.os.Bundle; public class vibrator extends Activity {
/** 定义变量 */ public static final int VIB_ON = 0x11; public static final int VIB_OFF = 0x22; vibClass mvibClass;/**定义类*/ @Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.main); /**----------------初始化------------- */ mvibClass = new vibClass();/*声明类*/ mvibClass.Init(); //调用JNI库里的初始化函数 /**----------------按钮:打开LED------------- */ Button btn1 = (Button)findViewById(R.id.led_on);/*这里用到的ID,就是在main.xml里定义的 led_on*/ btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) /**当按钮按下*/ {
mvibClass.IOCTLVIB(VIB_ON); } }); /**----------------按钮:关闭LED------------- */ Button btn2 = (Button)findViewById(R.id.led_off);/*声明按钮,id main.xml里有定义*/ btn2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) /**当按钮按下*/ {
mvibClass.IOCTLVIB(VIB_OFF); } }); } }

 

 

如果在保存时遇到说 save problems,无法保存,请先复制上面的代码,然后,关闭vibrator.java,提示保存时选不保存,然后在左边资源窗中再次双击打开该文件,把几日才复制下来的内容,粘贴上去,一般就能正常保存,不知道是不是Eclipse的不稳定造成的。

5、添加类vibClass

鼠标右键com.auly.control > new > Class

clip_image002[20]

填参数:

clip_image002[22]

Finish后,在/src/com/auly/control/得到如下的类文件

vibClass.java

修改如下

 

package com.auly.control; /*Class for Vibrator --peter*/ public class vibClass {
static {
System.loadLibrary("vib-jni");/*加载JNI库*/ } /*声明 函数*/ public static native String stringFromJNI();/*输出字符串 对应于JNI里面的 jstring Java_com_auly_control_vibClass_stringFromJNI( JNIEnv* env,jobject thiz ) */ public static native int Init();/*初始化函数,对应于JNI里面的 jint Java_com_auly_control_vibClass_Init( JNIEnv* env ) */ public static native int IOCTLVIB(int controlcode); /*IO CTRL 接口 * 对应于JNI里的 jint Java_com_auly_control_vibClass_IOCTLVIB( JNIEnv* env, jobject thiz, jint controlcode ) */ }

 

 

三、 编译运行

鼠标右键工程名,弹出菜单,选择 Run as > Android Application 就可以看到编译过程,编译完成后,会自动调用android模拟器,看到如下效果

clip_image002[24]

安装到开发板:

在C:/LEDSJNI目录下,会看到bin文件夹,里面的LEDAPP.apk就是这个程序的安装文件,可以把它安装的开发板上,运行本程序,看控制开发板上的LED灯的效果。

步骤:

1、开发板上跑的kenel就已经把了LED驱动编译在里面了,

可以参考《android驱动例子(LED灯控制)》

2、开发板android跑起来后,PC机打开串口工具例如DNW,打开与开发板连接的COM口,然后敲打回车,就会在终端里看到“#”并有光标,表面进入了开发板的命令行终端,

输入命令:

#chmod 777 /dev/vib

      这是为了使得vib这个节点可以被我们写的JNI操作,不然会open失败的,因为APK安装的JNI模块,权限不够,这个节点是我们的LED驱动生成的控制节点。

也可以在android文件系统yaffs编译时,通过init.rc 文件来实现这个操作,就是在该文件里随便一行,写上面的命令行,启动时会自动执行!这样就不用手动的改变该节点的属性了。

3、拷贝LEDAPP.apk到开发板上,通过安装工具把它安装到开发板上,如果不会安,可以GOOGLE一下,

4、运行程序,就能按程序上的近钮来控制开发板上的LED亮灭了!

 

     要学好嵌入式,还是建议买一个开发板,因为在枯燥学习中,要实践才会记忆深刻,而且,在看到自已学的知道能做出一些功能,会很有成就感,更能积累信心往深处学。例如学驱动开发,能在开发板上做出一个应用,调用自已写的驱动程序,控制LED灯的亮灭,这就很能鼓励自已,让自已更有兴趣往下学,这样学习来会更快!

 

  推荐使用 著名开源项目:树莓派3 卡片电脑,我个人觉得挺不错的,也非常的便宜,

 介绍看这里

 

 

csdn签名

转载于:https://www.cnblogs.com/wi100sh/p/4727307.html

你可能感兴趣的文章
【算法】字符串问题——数组中两个字符串的最小距离
查看>>
hdu1540 线段树(区间合并)
查看>>
Python----面试题(三)
查看>>
C# 后台三级联动
查看>>
17-文本属性和字体属性
查看>>
ReadWriteLock-读写分离锁
查看>>
(5)STM32使用HAL库实现串口通讯——实战操作
查看>>
STM32_NVIC寄存器详解
查看>>
fastcgi的介绍,原理及配置
查看>>
异常:调用链顺序
查看>>
检查PHP脚本的执行效率(xdebug)
查看>>
Servlet之Filter详解
查看>>
centos php php-fpm install
查看>>
JavaScript编码规范(2)
查看>>
python-docx操作word文件(*.docx)
查看>>
jmeter---接口测试
查看>>
bzoj4665: 小w的喜糖
查看>>
关于事件的小结
查看>>
Zoundry Raven测试
查看>>
第五章 团队和流程
查看>>