基于Android平台的串口通信实现

转自:http://www.reader8.cn/data/20110723/783131.html

摘要:串口在数据通信中应用广泛,但Android SDK指定使用Java作为第三方应用开发语言,这给C语言实现串口应用带来了困难。虽然Google Android已经发布了NDK(Native Development Kit,原生态开发包),支持开发者用C/C++语言开发Android程序,但目前官方提供的技术指导比较简略。通过开发一个Android下串口通信应用实例,详细介绍了Android NDK的开发流程,帮助开发人员快速的完成平台搭建。


关键词:Android;NDK;JNI;SDK;串口


Android是Google推出的基于Linux的开源手机操作系统,是一个专门针对移动设备设计的软件平台,包括操作系统、中间件和一些关键应用。它的软件架构包含四个层次,从高到低分别为应用层、应用框架层、系统运行层和linux内核层,如图1所示。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。Android发布初期,Google就表示其虚拟机Dalvik支持JNI编程方式,也就是第三方应用完全可以使用JNI调用自己的C动态库,但Google官方并没有明确表示支持开发者使用这种方法。终于在2009年6月,Google Android发布了NDK,它支持开发者使用C/C++语言开发Android程序。作为Android SDK的一个附加组件提供,开发者必须先安装Android SDK方可使用NDK。NDK的目的是为了增加代码的重用性及加快程序的运行速度,这有利于开发者从其他系统上移植软件到Android平台。
  1 Android NDK简介
  在Android上应用程序的开发大部分基于Java语言来实现。要使用C或是C++的程序或库,就需要使用NDK来实现。NDK是Native Development Kit的简称。它是一个工具集,集成了Android的交叉编译环境,并提供了一套比较方便的Makefile,可以帮助开发者快速开发C或是C++的动态库,并自动的将so动态库和java程序打包成apk,在Android上运行。有两个理由使用NDK:一是合理的重用现有的代码;二是在程序中某些关键的部分提高执行效率。
  Android NDK目前作为Android SDK的一个附加组件提供,开发者须先安装Android SDK方可使用NDK。在Windows平台下进行NDK开发通常会采用Cygwin。Cygwin是一套可以运行在Windows平台上的UNIX/Linux模拟器。运行Cygwin后会出现一个类似Windows CMD的Shell环境界面,可以使用大部分Linux软件和功能。使用它我们可以方便的在Windows平台编译出Linux平台的库文件或应用程序。
  2 安装和配置NDK开发环境
  2.1 安装NDK
  首先要完整安装SDK,尽量升级至最新版本,文中使用2.1版本的SDK。然后下载NDK,官网有三个版本分别是Windows、Mac OS X(intel)、Linux32/64(x86),下载后解压即可使用。文中使用Windows版本的NDK,版本为android-ndk-r5。将它解压到某个目录下,文中我们将NDK安装到D:\android\android-ndk-r5目录中。
  2.2 安装Cygwin
  首先去Cygwin官网下载网络安装程序,下载下来以后点击直接运行。安装过程中最关键的是选择需要安装的包,为支持Android NDK的开发,选择Default安装后再安装以下模块autoconf2.1、automake1.10、binutils、gcc-core、gcc4-core、gdb、pcre、pcre-devel、GNU awk。 
  下面开始将Android NDK配置到Cygwin中。运行Cygwin,修改Cygwin目录下(/home/usrname)的.bash_profile文件,在文件尾部加入如下代码,
  NDK=/cygdrive/d/android/android-ndk-r5
  export NDK
  然后重新启动Cygwin。输入cd $NDK,如果输出上面配置的/cygdrive/e/android-ndk-r5信息,则表明环境变量设置成功了。接下来就可以用 Cygwin 来编译我们的NDK代码了。
  3Android NDK开发实例 
  开发实例是一个Android平台上的收音机程序,该应用通过调用串口API与外围收音机芯片通信,进而控制收音机芯片完成搜台、显示等功能。
  Android NDK开发一般有以下步骤:
  1) JNI接口设计;
  2) 使用C/C++实现本地方法;
  3) 生成动态链接库;
  4) 将动态链接库复制到Java工程,生成.apk文件。
  首先,创建一个NDK工程,然后在这个文件夹下建立jni和src两个目录,jni用来存放我们的C文件,src是调用C库的Java接口文件。接着创建jni/SerialPort.c,该文件的主要作用是完成串口的打开和关闭。关键代码如下:


[java]  view plain copy print ?
  1. Java_android_serialport_SerialPort_open(JNIEnv *env, jobject thiz, jstring path, jint baudrate) {  
  2.   ……  
  3.   /* Opening device */  
  4.   const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);  
  5.   LOGD("Opening serial port %s", path_utf);  
  6.   fd = open(path_utf, O_RDWR | O_DIRECT | O_SYNC);  
  7.   LOGD("open() fd = %d", fd);  
  8.   (*env)->ReleaseStringUTFChars(env, path, path_utf);  
  9.   ……  
  10.   /* Configure device */  
  11.   ……  
  12.   struct termios cfg;  
  13.   cfmakeraw(&cfg);  
  14.   cfsetispeed(&cfg, speed);  
  15.   cfsetospeed(&cfg, speed);  
  16.   }  

在文件中,函数名这样定义:
  jobject JNICALL Java_android_serialport_SerialPort_open,这个是JNI的标准,定义需要按照如下格式:Java_packagename_classname_methodname
  接着创建文件jni/Android.mk.这个文件是我们本地c代码的Makefile。文件内容如下:
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
  LOCAL_MODULE:= serial_port
  LOCAL_SRC_FILES := SerialPort.c
  LOCAL_LDLIBS:= -llog
  include $(BUILD_SHARED_LIBRARY)
  LOCAL_PATH:=$(callmy-dir)这句用来指定编译的路径通过调用宏my-dir获取到当前工作的路径。
  include$(CLEAR_VARS) CLEAR_VARS这个变量是编译系统提供的用来指明一个GNU makefile文件添加这句主要的目的是清理所有的LOCAL_XXX,比如LOCAL_MODULE、LOCAL_SRC_FILES等。在每个新模块的开始处需要添加这句。
  LOCAL_MODULE := serial_port这句定义了模块名称,将来编译的库或者可执行程序就以此命名。如果编译的是动态库或者静态库,那么库名就是libserial_port.so或者libserial_port.a。需要注意的是系统会在生成动态库或者静态库的时候自动添加lib的前缀。
  LOCAL_SRC_FILES := SerialPort.c是列出需要编译的源码文件名。这里不需要列出头文件和被包含文件,因为编译系统会自动为你添加。
  include$(BUILD_SHARED_LIBRARY)这句说明将来产生的库是共享库即动态链接库。
  接着,我们就可以在cygwin下编译生成库文件了。如图2所示,进入到工程目录下,运行ndk-build命令,生成了名为libserial_port.so的文件。
  将该文件安装到工程目录下的libs\armeabi目录中。然后在src目录下编写的serialport.java文件,该文件用于JNI接口调用。关键代码如下:

  1. public class SerialPort {  
  2.   ……  
  3.   /*open the serial port*/  
  4.   mFd = open(device.getAbsolutePath(), baudrate);  
  5.   // JNI  
  6.   private native static FileDescriptor open(String path, int baudrate);  
  7.   public native void close();  
  8.   static {  
  9.   System.loadLibrary("serial_port");  
  10.   }  
  11.   }  

private native static FileDescriptor open(String path, int baudrate)这句申明,带有native关键字,说明该方法是本地方法。System.loadLibrary("serial_port")这句就是用来加载我们的c动态库的。上面声明方法的具体实现就在我们加载的库中。
  在完成了上述工作后,我们就可以针对具体应用来使用串口完成数据通信了。文中通过按键搜台,并显示出具体频段。
  界面布局采用xml文件来声明,主要包括两个Button和一个TextView视图。
  在Button上添加了按键响应,当按下Button时通过串口发送调频信号。

  1. bforeward.setOnClickListener(new View.OnClickListener() {  
  2.   public void onClick(View v) {  
  3.   try {  
  4.   mOutputStream.write('+');  
  5.   mOutputStream.write('\n');  
  6.   } catch (IOException e) {  
  7.   e.printStackTrace();  
  8.   }  
  9.   }  
  10.   });  

TextView用于接收串口信息,显示调频。
  
  1. protected void onDataRecEived(final byte[] buffer, final int size) {  
  2.   runOnUiThread(new Runnable() {  
  3.   public void run() {  
  4.   if (mReception != null) {  
  5.   mReception.setText(new String(buffer, 0, size));  
  6.   }  
  7.   }  
  8.   });  
  9.   }  


  同时添加了Menu,当按下Menu键时可以选择“退出”或“关于”。
  
  1. //添加菜单选项  
  2.   @Override  
  3.   public boolean onCreateOptionsMenu(Menu menu) {  
  4.   menu.add(0, 0, 0,R.string.about);  
  5.   menu.add(0, 1, 1,R.string.exit);  
  6.   return true;  
  7.   }  
  8.   //实现选择菜单的动作  
  9.   @Override  
  10.   public boolean onOptionsItemSelected(MenuItem item) {  
  11.   int item_id = item.getItemId();  
  12.   switch(item_id) {  
  13.   case 0:  
  14.   ……  
  15.   case 1:  
  16.   MainMenu.this.finish();  
  17.   break;  
  18.   }return true;  
  19.   }  


  编译运行该工程,就可以生成apk文件了。将apk文件和libserial_port.so安装到Android平台后,运行该应用程序,运行结果如图所示。
  4结论
  Android NDK使C语言开发人员也能参与到Android应用程序的开发中,增加代码的重用性。文中通过搭建串口应用的C代码底层接口,验证了其平台的可用性。但目前NDK还处于初级阶段,官方表示后期将提供更多的库,相信今后Android会对“C组件支持”更完善。
  参考文献:
  [1] 赵宏伟.Android NDK开发环境实现与应用[J].电脑知识与技术,2010(35).
  [2] 杨丰盛.Android应用开发揭秘[M].北京:机械工业出版社,2010:484.
  [3] Android SDK Document[EB/OL].http://developer.android.com/guide/index.html.
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值