文章快速检索  
  高级检索
基于JNI技术的3G模块控制研究和实现
王百青, 付永庆
哈尔滨工程大学 信息与通信工程学院,黑龙江 哈尔滨 150001    
摘要:为了研究Android系统的应用程序如何通过JNI技术实现对底层设备的操作,文中以3G模块实验为例,介绍了Android系统的Linux内核对3G模块常用控制引脚的驱动实现。结合JNI和Android NDK技术调用本地方法,并在Eclipse下编程实现Android应用程序对3G模块的常用操作(如复位、飞行模式等).实践证明通过JNI技术可实现Android应用程序操作底层设备。
关键词Android系统     Linux内核     3G模块     JNI技术     Android NDK    
Research and implementation of 3G module control based on JNI technology
WANG Baiqing , FU Yongqing     
College of Information and Communication Engineering, Harbin Engineering University, Harbin 150001, China
Abstract:In order to get the way by which the application of Android system can control the bottom devices through JNI technology, the 3G module is used for the experiment. The driver implementation of 3G module controlling pins in Linux kernel of Android operating system was introduced. Besides, using JNI and Android NDK technology, and calling the native methods, it achieves the Android application which is developed in the IDE of Eclipse to operate 3G module, such as reset, flight mode, and so on. It is verified that the bottom equipment can be operated by Android application program through JNI technology.
Key words: Android operating system     Linux kernel     3G module     JNI technology     Android NDK    

作为基于Linux内核的操作系统,Android系统自推出以来,就以“开源”特性逐渐占据了嵌入式设备操作系统的主要市场份额,成为现有主要的嵌入式系统如iOS、Windows Phone、Android等市场占有率最高的操作系统。Android SDK (software development kit )中指定使用Java作为第三方应用开发语言[1],且Java应用程序运行在Dalvik虚拟机中。运行在虚拟机中的Java代码可以充分利用Java语言的平台无关性,但是一定程度上造成了Android应用程序很难操作底层硬件的缺点。为此Android系统中引入了JNI机制——利用Java的JNI机制,使用Android NDK( native development kit )编译环境,应用程序可以透过Android系统的应用框架层,直接在Linux的文件系统对设备进行操作[2]。文中讨论了在Android系统中通过应用程序控制3G模块的常用接口——复位、飞行模式等,讨论了JNI技术在Android系统中的应用价值和意义。

1 Android JNI和NDK介绍

Android系统架构采用了分层结构,保证了层与层之间相互分离,当某一层发生变化时,其他层受影响很少[3]。如图 1所示,从底层到顶层分别是Linux内核层、系统库和Android运行时库、应用框架层和应用程序层[4]

JNI是JDK( Java native kit )的一部分,可以允许Java代码和其他语言写的代码进行交互,以实现代码在不同的平台上移植。通过JNI,可以使得运行于JVM( Java virtual machine )的代码调用C、C++等[5]语言编写的应用程序或库[6],同时也可以通过调用相应的接口函数将Java虚拟机内嵌到本地应用程序中[7]。JNI机制调用本地的C/C++代码库,可以充分利用C/C++代码的高效性,来提高应用程序的运行效率。

Android NDK本质上是一系列的工具集,用来完善Android应用更加便捷的使用本地代码,如C或C++代码[8]。因此,用户可以使用NDK将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率,而且可避免Java包都是可以反编译的不安全性[9]。Android系统的层次结构如图 1所示。

图 1 Android系统的层次结构

2 MU739模块控制引脚及驱动实现

MU739为华为公司推出的支持WCDMA、HSPA+的LGA 3G模块,采用USB接口。在HSPA+模式下,上行速率可以达到5.76 Mbit/s,下行速率可以达到21.6 Mbit/s。在Linux内核中,对USB 3G模块的驱动位于USB设备驱动层[10, 11],如图 2所示。

图 2 USB 3G模块的驱动在Linux内核中的位置

在3G模块的驱动移植完成后,为实现对3G模块的控制,文中选取了MU739模块的上电控制引脚(ON1、ON2_N)、复位控制引脚(PWRDWN_N)、飞行模式控制引脚(W_DISABLE_N)和休眠控制引脚(WAKEUP_IN)来实现控制3G模块的工作状态。下面依次介绍这几个引脚的主要功能。

1) ON1和ON2_N引脚用于打开3G模块,其中ON1引脚设置为默认高电平,ON2_N通过控制引脚提供开机时序,使3G模块在上电之后处于工作状态;

2) PWRDWN_N引脚用于复位整个模块系统,使基带、电源管理单元、RF单元进入初始状态;

3) W_DISABLE_N引脚用于使模块进入飞行模式,关闭模块的RF单元;

4) WAKEUP_IN引脚用于CPU来控制3G模块的睡眠状态,当设置为高电平时,CPU唤醒MU739,当电平为低时,CPU使MU739进入睡眠模式。

2.1 配置控制引脚为GPIO模式

设计中采用的CPU为飞思卡尔公司的iMX536多媒体处理器,该处理器采用ARM CortexTM-A8 内核,在车载环境中可以实现800 Hz的工作频率。为了实现对片内多种功能模块的支持,iMX53x系列处理器采用IOMUX机制实现对IO引脚的复用分配。

对3G模块的控制,主要通过iMX536处理器的IO控制实现。为此,需要在平台设备的配置文件中,配置对应的IO引脚为GPIO模式:

MX53_PAD_GPIO_19__GPIO4_5,//ON2

MX53_PAD_PATA_DA_2__GPIO7_8,// PWRDWN

MX53_PAD_PATA_CS_0__GPIO7_9,// W_DISABLE

MX53_PAD_PATA_CS_1__GPIO7_10,// WAKEUP_IN

并给与ON2_N的控制引脚实现模块的开启时序(见图 3所示)。

图 3 开启3G模块的时序图

gpio_direction_output(ON2,1);

udelay(40);

gpio_direction_output(ON2,0);

其中,ON2为宏定义——#define ON2(3×32+5) /*GPIO_4_5*/

2.2 控制驱动程序的编写

为实现对底层设备的操作,需要编写对应的控制驱动程序。因此,为实现对上述IO引脚的控制,需要编写对应的驱动代码,即字符型设备驱动。需要首先实例化Linux内核中描述设备文件操作的结构体file_operations(位于Linux内核include/linux/下的Fs.h文件),其中定义了操作驱动设备的主要操作接口函数指针。下面所示代码为在本驱动代码中实例化结构体file_operations:

static struct file_operations mu739_cont_fops={

.owner = THIS_MODULE,

.open = mu739_cont_open,

.read = mu739_cont_read,

.write = mu739_cont_write,

.ioctl = mu739_cont_ioctl,

.release = mu739_cont_release,

};

上述函数指针中,主要实现功能的函数为mu739_cont_ioctl,该函数的实现原理是通过获取打开设备时传入的参数值,来执行对应的IO控制输出,以实现对应控制引脚的控制时序(见图 4)。

图 4 3G模块控制时序

static int mu739_cont_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg){

if(arg > 4){

return -EINVAL;

}

printk(KERN_ERR"mu739_cont_ioctl --CMD=%x /n",cmd);

switch(cmd){

case IOSIGNAL_REST:

……// reset the module

return 0;

case IOSIGNAL_AIRMOD://

……// set the module in airplane mode

return 0;

case IOSIGNAL_UAIRMOD:

……// set the module in normal mode

return 0;

case IOSIGNAL_WAKEUP:

……// wake up the module

return 0;

case IOSIGNAL_UWAKEUP:

……// set the module in sleep mode

return 0;

default: break;

}

}

在驱动代码最后,实现模块的初始和注销函数如下:

static int __init MU739_cont_init(void){

int ret;

//调用register_chrdev方法注册设备驱动

ret=register_chrdev(MU739_MAJOR,DEVICE_NAME,&mu739_cont_fops);

if(ret < 0){

printk(DEVICE_NAME"cant register major No.\\n");

return ret;

}

……

return 0;

}

static void __exit MU739_cont_exit(void){

// 调用unregister_chrdev方法注销设备

unregister_chrdev(MU739_MAJOR,DEVICE_NAME);

……

}

module_init(MU739_cont_init);

module_exit(MU739_cont_exit);

最后,将该驱动静态添加进内核中。编译烧写后,会在Android系统的dev/目录下查看到该设备mu739_cont_dev。

3 应用程序编写

在Eclipse开发环境中新建一个Android应用工程mu739_control,用来作为控制3G模块的Android应用程序。

3.1 编写调用本地方法

在mu739_control工程目录下新建包com.example.myjni,用于声明native方法以及给应用程序调用的静态库名字:

public static native int open3G(int flag);

static{

System.loadLibrary("ContModule");

}

其中native关键字用于告知编译器该方法为本地方法;static关键字包括的语句System.loadLibrary("ContModule"),表示调用本地库文件为libContModule.so(其命名规则是libFileName.so)。

之后,在工程目录中,新建空文件夹jni,用于存放jni文件。并通过终端进入工程的根目录下,运行命令javah,生成JNI头文件:

$ javah -classpath bin/classes -d jni/ com.example.myjni.MyNative

其中,javah命令为NDK开发环境中带有的工具,其用法如图 5所示。

图 5 javah命令的使用方法

javah命令生成的头文件名字为com_example_myjni_MyNative.h,其中包含了上述本地方法的声明方式:

JNIEXPORT jint JNICALL Java_com_example_ myjni_MyNative_open3G(JNIEnv *,jclass,jint);

之后,在jni/目录下新建C文件myfile.c,实现上述函数的功能:

JNIEXPORT jint JNICALL Java_com_example_ myjni_MyNative_open3G(JNIEnv *env,jclass thiz,jint flag){

int temp,ledstatus = flag;

int fd;

// 调用open函数打开设备mu739_cont_dev

fd = open("/dev/mu739_cont_dev",O_RDWR);

if(fd < 0){

LOGE("Open 3G device error,fd = %d .",fd);

exit(1);

}

// 打开设备后,调用ioctl函数,操作设备并传入控制参数

temp = ioctl(fd,ledstatus,0);

sleep(10);

if(temp < 0 ){

LOGE("ioctl the device error,lestatus = %d",ledstatus);

exit(1);

}

// 完成操作后,调用close函数,关闭设备

……close(fd);

return 1;

}

然后,在jni/目录下编写Android.mk文件,用来指导编译工具编译上述C文件:

LOCAL_PATH := $(call my-dir)

#include $(CLEAR_VARS)

LOCAL_LDLIBS := -llog

LOCAL_MODULE := ContModule

LOCAL_MODULE_FILENAME := libContModule

LOCAL_SRC_FILES := myfile.c

include $(BUILD_SHARED_LIBRARY)

最后,在终端运行命令# ndk-build编译,即可在libs/armeabi/目录下生成.so库文件libContModule.so。即为System.loadLibrary()中引用的静态库文件。

3.2 JAVA代码实现

编写Android应用代码,实现对上述本地方法的调用。

在Android应用工程中开发一个Android应用界面(如图 6所示),界面上的按键采用监听的方式处理对3G设备的操作。

图 6 Android应用程序控制界面

在代码中,实现对上述按键的监听,为减少函数调用时引起的延时,响应按键的函数在新建的线程中实现。监听按键的onClick函数代码如下:

@Override

public void onClick(View arg0) {

switch(arg0.getId()){

case R.id.Button_Rest: // 对复位按键处理

Log.d(TAG,"Rest the 3G module");// Log调试信息

new Thread(new Runnable() { // 新线程中处理

public void run() {

MyNative.open3G(Rest_Flag);

}

}).start();

break;

case R.id.Button_Normal: // 正常模式

Log.d(TAG,"Set the module Normal Mode");

new Thread(new Runnable() {

public void run() {

MyNative.open3G(Norm_Flag);

}

}).start();

break;

case R.id.Button_Airmode: // 飞行模式

Log.d(TAG,"Set the module Airmode");

new Thread(new Runnable() {

public void run() {

MyNative.open3G(Airm_Flag);

}

}).start();

break;

case R.id.Button_Wakeup:

Log.d(TAG,"WakeUP 3G module");

new Thread(new Runnable() {

public void run() {

MyNative.open3G(Wake_Flag);

}

}).start();

break;

case R.id.Button_Sleep: // 对睡眠模式处理

Log.d(TAG,"Set the module sleep");

new Thread(new Runnable() {

public void run() {

MyNative.open3G(Slep_Flag);

}).start();

break;

}// switch(arg0)

}// onClick

4 结束语

通过介绍Android系统应用层代码对3G模块复位等控制引脚的操作,讨论了Android应用中使用JNI技术控制底层设备的实现方法和步骤,对于涉及到底层设备操作(如串口等)的应用设计具有指导意义。在下一步的研究中,可以结合硬件抽象层实现底层和应用层的隔离,讨论及实现应用层对底层设备的操作。

参考文献
[1] 金智义, 张戟. 基于Android平台的串口通信实现[J]. 电脑知识与技术, 2011, 7(13): 2983-2990.
[2] 高海彬. JNI在Android系统下串口控制的应用[J]. 信息技术, 2013(10): 173-176.
[3] 李刚. 疯狂Android讲义[M]. 2版. 北京: 电子工业出版社, 2011: 78-79.
[4] 高海彬. JNI在Android系统下串口控制的应用[J]. 信息技术, 2011(10): 173-176
[5] 丁海洋, 姚佳楠, 王明飞. 基于移动平台的印刷网点检测技术[J]. 北京印刷学院学报, 2014(8): 50-65.
[6] 张华平, 玄光哲,于贵平, 等. 基于JNI技术应用框架的分析和实现[J]. 吉林大学学报: 信息科学, 2003, 21(2): 188-191.
[7] 任俊伟, 林东岱. JNI技术实现跨平台开发的研究[J]. 计算机应用研究, 2005(7): 180-184.
[8] Google. Android Developer website[EB/OL]. [2012-09-02]. http://developer.android.com.
[9] 王二伟. 基于Android平台人脸检测与识别研究[D]. 西安: 西安电子科技大学, 2013: 11-22.
[10] 刘淑峰. 基于 Android 的多媒体与 3G 上网子系统设计与实现[D]. 哈尔滨: 哈尔滨工业大学, 2012: 63-64.
[11] 宋世磊, 刘晓平, 应怀樵. 基于ARM-Linux的USB 3G模块设备驱动的研究[J]. 计算机工程与应用, 2011: 175-178.

文章信息

王百青, 付永庆
WANG Baiqing, FU Yongqing
基于JNI技术的3G模块控制研究和实现
Research and implementation of 3G module control based on JNI technology
应用科技, 2015, (03): 35-39
Applied Science and Technology, 2015, (03): 35-39.
DOI:10.3969/j.issn.1009-671X.201410002

文章历史

收稿日期:2014-10-13
网络出版日期:2015-04-20

相关文章

工作空间