android sudio 在项目中使用android-serialport-api 实现串口通讯,基于RK3128

安卓没有直接实现串口通讯的API,所以需要用到Google开源的代码,通过JNI的方式实现串口通讯。android-serialport-api的代码和wiki如下:

android-serialport-api_code
android-serialport-api_wiki

Google的这个代码比较老,所以是基于eclipse实现的,我以前也写过一篇基于eclipse实现JNI库的文章,但是接触了谷歌亲儿子android studio之后才发现,调用JNI是这么简单方便,即使是老旧的eclipse项目也可以很好的支持。
调用JNI的方法网上有很多博客,但是我认为还是官网给出的方案最好,配合Android studio可以最精简地实现JNI支持,找到了中文版的如下:
add-native-code, 看完这个之后应该就对JNI有很好的了解并能够熟练(以正确的方式)操作了。
本文结合上述官网wiki,讲一下怎么在自己的项目里调用android-serialport-api 。

预备工作

  1. 安装Android studio、NDK、SDK、CMake、LLDB等略去不表,看上面的wiki即可。
  2. 准备一块能串口通讯的板子,和USB转TTL的串口小板,我用的分别是RK3128的UART和CP2102。并在PC上装好CP2102的驱动和串口调式程序,可以在淘宝上找到。
  3. 下载上述的Google串口源码,并且建议先连好所有硬件后,用提供的apk试一下硬件有没有问题。apk_download,下1.1版本的,如果这个示例程序可以实现串口的收发,我们可以接下来研究如何调用了。注意,选串口的时候/dev/ttyS0这些,可能要多试几个。如果都不可以的话,可能是需要root之类的权限问题。在RK3128上对串口的支持比较好,亲测无需root也可以玩串口。
  4. 观察android-serialport-api的结构,对我们有用的是android-serialport-api/project/目录。其中jni目录表示C源码和ndk-build的依赖文件,src/android_serialport_api/目录下的SerialPort.java和SerialPortFinder.java是串口类,以上是我们调用的关键,可以通过src/android_serialport_api/sample中的例程熟悉调用的方法。

往项目中迁移android-serialport-api代码

  1. 在项目名/app/src/main/java下创建android_serialport_api目录,将android-serialport-api/android-serialport-api/project/src/android_serialport_api/目录下的SerialPort.java和SerialPortFinder.java复制到android_serialport_api目录下
    android sudio 在项目中使用android-serialport-api 实现串口通讯,基于RK3128_第1张图片
  2. 在project状态下右键main,New-Folder-JNI Folder. 并将android-serialport-api/android-serialport-api/project/jni目录下的除了gen脚本以外的四个文件拷入刚刚创建的文件夹,完成1、2两步后结构应该如下图所示:
    android sudio 在项目中使用android-serialport-api 实现串口通讯,基于RK3128_第2张图片

往项目中增加C++支持-JNI

这一部分是关键,也是网上各种方案的区别之处。但是从官网可以看到,很多博主的方法都太老了也太复杂了,实际上Android studio已经很好地集成好了对eclipse下JNI项目的支持,即将 Gradle 关联到您的原生库中提供的2种方式的第二种,使用 Android Studio UI并选择ndk-build,请使用 Project Path 旁的字段为您的外部 ndk-build 项目指定 Android.mk 脚本文件。如果 Application.mk 文件与您的 Android.mk 文件位于相同目录下,Android Studio 也会包含此文件
指向我们之前加入的jni目录下的Android.mk后,android-serialport-api对应的JNI支持就已经完成了。注意,不需要像很多博客说的一样强行用CMakeLists.txt的方法构建,增加不必要的麻烦。

在项目中调用android-serialport-api

调用方法可以研究src/android_serialport_api/sample的例程,这个实际上就是之前提到的apk的Android源码。应该内容比较好懂,具体到我们的项目,首先在我们自己项目的主Activity中import SerialPort和其他的需要包,并增加定义串口需要的变量。

import android_serialport_api.SerialPort;
import android_serialport_api.SerialPortFinder;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidParameterException;
import android.content.SharedPreferences;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;

  protected SerialPort mSerialPort;
  protected OutputStream mOutputStream;
  private InputStream mInputStream;
  private ReadThread mReadThread;		//接收线程
  byte[] mBuffer;		//接收缓存

并在OnCreate方法中打开串口:不一定是ttyS0,和使用的UART有关,可以通过apk例程试出来并自行修改,并设置波特率。

    try {
      /* 打开串口 */
      mSerialPort = new SerialPort(new File("/dev/" + "ttyS0"), 115200, 0);
      mOutputStream = mSerialPort.getOutputStream();
      mInputStream = mSerialPort.getInputStream();

      mBuffer = new byte[128];
      /* Create a receiving thread */
      mReadThread = new ReadThread();/* 创建串口接收程序 */
      mReadThread.start();

    } catch (SecurityException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

并实现串口接收线程:

  private class ReadThread extends Thread {

    @Override
    public void run() {
      super.run();
      while(!isInterrupted()) {
        int size;
        try {
          byte[] buffer = new byte[64];
          if (mInputStream == null) return;
          size = mInputStream.read(buffer);
          if (size > 0) {
          	//处理串口
            LOGGER.i("receiving"+buffer[0]);
          }
        } catch (IOException e) {
          e.printStackTrace();
          return;
        }
      }
    }
  }

这样就完成了简单的接收串口数据的流程,可以试一下用PC发送,能否通讯,理论上效果应该是和apk例程的console模式时一样的。
发送也很简单,可以参照例程中Sending01010101Activity.java的写法。
祝大家用的顺利~

你可能感兴趣的:(安卓学习笔记)