本文转自:http://blog.csdn.net/ok138ok/article/details/6560875

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

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

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

一、编写JNI模块

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

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

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

vib-jni.c文件

#include <string.h>
#include <jni.h>
#include <fcntl.h> /*包括文件操作,如open() read() close() write()等*/
//----for output the debug log message
#include <android/log.h>
#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

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

二、JAVA程序

1、Eclipse新建工程

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

新键工程后,

如果出现如下错误:

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

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

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

2、加入button和文本输出

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

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
androidrientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button android:id="@+id/led_on"/*这表示需要一个唯一的UID来作为Button的ID,它的引用名是led_on。*/
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/LEDon">/*表示这个按钮的文本是来源于另一个资源描述文件strings.xml里的文:字资源LEDon */
<requestFocus/>
</Button>
<Button android:id="@+id/led_off"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/LEDoff">
<requestFocus/>
</Button>
</LinearLayout>


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

3、加入输出字符串资源

工程 > values > strings.xml 文件

修改如下<?xml version="1.0" encoding="utf-8"?><resources>    <string name="hello">Led 控制程序</string>    <string name="app_name">LEDAPP</string><string name="LEDon">打开LED</string><string name="LEDoff">关闭LED</string></resources>

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

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

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

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

填参数:

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模拟器,看到如下效果

安装到开发板:

在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灯的亮灭,这就很能鼓励自已,让自已更有兴趣往下学,这样学习来会更快!

推荐下面4款,你可以根据你的经济能力来选一个


1、高级嵌入式开发板 ARM-A8内核,价格在2200~2700
X-210开发板(代码开放度高,XBOOT很牛)
Mini210开发板(友善的板子,有沉淀)

2、入门级嵌入式开发板 ARM11内核 ,价格在500~650之间
Tiny6410 (友善之臂经典之作)
OK6410 (特点是支持WINCE7.0)

可以去风火轮团队的店里看一下,在他们那里买板有个好处,他们提从更周到的技术支持

风火轮技术开发团队 http://www.arm-cn.com/

官方淘宝店:smartfire.taobao.com


更多相关文章

  1. Android(安卓)解析gbk、gb2312编码的xml文件(转)
  2. Android入门教程(三十)------之XML解析与生成
  3. android 提升性能总结
  4. Android番外篇——XML layout与CSS
  5. Android(安卓)Studio SVN配置忽略文件 1.用Android(安卓)Studio
  6. Android(安卓)自定义button简单示例
  7. android操作文件
  8. Android(安卓)屏幕适配之屏幕分辨率(创建不同dimen)适配
  9. 修改Android(安卓)Media Scanner的扫描路径

随机推荐

  1. Android(安卓)UI效果之绘图篇(四)
  2. 解决Android(安卓)studio 2.3升级到Andro
  3. Android(安卓)Fragment学习笔记(一)
  4. Android(安卓)CTS 测试研究之二
  5. 大家帮忙看看简历
  6. import project后,出现Unable to get syst
  7. Android(安卓)API 中文 (52) —— ZoomButt
  8. Android(安卓)5.1 Lollipop Phone工作流
  9. 8个android 游戏引擎
  10. Android(安卓)NoHttp源码阅读指导