最近涉及到android串口和usb的开发,花费不少时间找文章参考。主要时间花费在串口连接上,由于计算机实际中没有串口的设备接口,只能用 虚拟串口 进行通信;且 USB 连接模拟器又是一番费神操作。
用到的工具 提取码: djss
搭建虚拟环境(有实际串口接口可忽略)
-
打开 Genymotion 安装android虚拟机
-
打开android studio 添加 Genymotion 插件
-
打开 Oracle VM VirtualBox 添加 Oracle_VM_VirtualBox_Extension_Pack 插件
添加此支持在使用USB挂载android模拟器时必须使用,否则android模拟设备无法识别连接设备。
-
打开 Configure Virtual Serial Port Driver 添加虚拟串口
此处添加的虚拟串口是成对出现。 -
Oracle VM VirtualBox 开启使用虚拟串口
由于 成功回显图 模拟的串口名为COM2和COM3,此处仅开启COM2的映射即可。
-
Oracle VM VirtualBox 开启使用USB设备
此处选择自己开发的相应设备即可。 -
使用 串口调试精灵 模拟数据的发送与接收
上图为 开启状态 ,默认是关闭的 最后就是接下来要说的开启 android模拟器 并编写的程序进行通信
一、串口通信
参考链接 主要参考其使用谷歌的串口so库加载打开串口类
搭建项目
- 复制so库至android项目中
这里有个7.0系统会报错,so库版本问题,直接去谷歌开源拿比较稳
- 设置so库目录
android {
...
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
...
}
- 复制包及SerialPort类
注:android_serialport_api 包名不可更改
- 串口基本操作(打开,关闭,发送,接收)
//isConConnectionStatus 串口的连接状态
/**
* 打开串口
* @param pathname 串口路径
* @param baudrate 波特率
*/
public boolean openSerialPort(String pathname, int baudrate) {
boolean isopen = false;
try {
serialPort = new SerialPort(new File(pathname), baudrate, 0);
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
receive();//接收函数,主要实现开启子线程并读取数据
isConConnectionStatus = isopen = true;
} catch (IOException e) {
Log.e(TAG, "打开串口异常" + e);
} catch (SecurityException e) {
Log.e(TAG, "无串口操作权限" + e);
} catch (UnsatisfiedLinkError e) {
Log.e(TAG, "so文件无法加载" + e);
}
return isopen;
}
/**
* 接收串口数据
*/
public void receive() {
if (receiveThread != null && !isConConnectionStatus) {
return;
}
receiveThread = new Thread() {
@Override
public void run() {
while (isConConnectionStatus) {
try {
byte[] readData = new byte[32];
if (inputStream == null) {
return;
}
int size = inputStream.read(readData);
if (size > 0 && isConConnectionStatus) {
//回调数据
Log.i(TAG, "readData:" + Arrays.toString(readData));
}
} catch (IOException e) {
Log.e(TAG, "读取数据失败..." + e);
}
}
}
};
receiveThread.start();
}
/**
* 发送串口指令
*/
public boolean sendData(byte[] data) {
boolean result = false;
if (isConConnectionStatus) {
try {
outputStream.write(data);
outputStream.flush();
result = true;
} catch (IOException e) {
Log.e(TAG, "串口数据发送失败:" + e);
}
}
return result;
}
/**
* 关闭串口
*/
public boolean closeSerialPort() {
boolean isclose = false;
if (isConConnectionStatus) {
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
isConConnectionStatus = false;
isClose = true;
} catch (IOException e) {
Log.e(TAG, "关闭串口异常" + e);
}
}
return isclose ;
}
串口的操作就在这里完结撒花。
二、USB通信
- 设置静态权限
<uses-feature android:name="android.hardware.usb.host" />
- USB基本操作(打开、关闭、接收、发送)
public void open() {
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
if (usbManager != null) {
UsbDevice result = null;
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
for (String key : deviceList.keySet()) {
UsbDevice usbDevice = deviceList.get(key);
if (usbDevice != null &&
usbDevice.getProductId() == PID &&
usbDevice.getVendorId() == UID) {
result = usbDevice;
break;
}
}
if (result != null) {
if (usbManager.hasPermission(result)) {
onUsbPermissionAllow(result);//权限通过
} else {
//申请USB权限
mUsbPermissionActionReceiver = new UsbPermissionActionReceiver();
mUsbPermissionActionReceiver.setListener(this);
Intent intent = new Intent(UsbPermissionActionReceiver.ACTION_USB_PERMISSION);
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
IntentFilter permissionFilter = new IntentFilter(UsbPermissionActionReceiver.ACTION_USB_PERMISSION);
context.registerReceiver(mUsbPermissionActionReceiver, permissionFilter);
usbManager.requestPermission(result, mPermissionIntent);
}
} else {
onUsbPermissionAllow(null);
}
} else {
onUsbPermissionFail();//未获取到权限
}
}
public void onUsbPermissionFail() {
if (mUsbPermissionActionReceiver != null && context != null) {
context.unregisterReceiver(mUsbPermissionActionReceiver);
}
}
public void onUsbPermissionAllow() {
usbDeviceConnection = usbManager.openDevice(usbDevice);//获取usb连接
if (usbDeviceConnection != null) {
if (usbRequest == null) {
usbRequest = new UsbRequest();
}
usbRequest.initialize(usbDeviceConnection, usbEndpointIn);
isConConnectionStatus = true;
new ReceiveThread().start();
}
if (mUsbPermissionActionReceiver != null && context != null) {
context.unregisterReceiver(mUsbPermissionActionReceiver);
}
}
/**
* 接收线程
*/
private class ReceiveThread extends Thread {
@Override
public void run() {
super.run();
while (isConConnectionStatus) {
try {
int maxSize = usbEndpointIn.getMaxPacketSize();
receiveBytes = new byte[maxSize];
boolean result = false;
if (usbDeviceConnection != null && usbInterface != null) {
usbDeviceConnection.claimInterface(usbInterface, true);//独占接口
result = usbDeviceConnection.bulkTransfer(usbEndpointIn, receiveBytes, receiveBytes.length, DEFAULT_TIMEOUT) != -1;
}
if (result) {
//获取成功
Log.e(TAG, "data:" + e);
} else {
Log.e(TAG, "读取数据失败!\n" + e);
}
} catch (InterruptedException e) {
Log.e(TAG, "数据读取异常:" + e);
}
}
}
}
/**
* 发送串口指令(字符串)
*
* @param sendBytes 需要发送的字节数据
*/
private boolean sendData(final byte[] sendBytes) {
boolean sendResult = false;
if (usbEndpointOut != null && sendBytes != null && sendBytes.length > 0) {
sendResult = usbDeviceConnection.bulkTransfer(usbEndpointOut, sendBytes, sendBytes.length, DEFAULT_TIMEOUT) != -1;
}
Log.i(TAG, "sendData:" + sendResult);
return sendResult;
}
/**
* 关闭USB连接
*/
public boolean close() {
boolean result = false;
if (isConConnectionStatus) {
if (usbDeviceConnection != null && usbInterface != null) {
isConConnectionStatus = false;
usbDeviceConnection.releaseInterface(usbInterface);
usbDeviceConnection.close();
result = true;
}
}
return result;
}
UsbPermissionActionReceiver 类
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.util.Log;
import ehe.etsa.serialport.IETSAFactory;
public class UsbPermissionActionReceiver extends BroadcastReceiver {
private OnUsbPermissionListener listener;
public static final String ACTION_USB_PERMISSION = "com.demo.USB_PERMISSION";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (null != usbDevice && listener != null) {
listener.onUsbPermissionAllow(usbDevice);
}
} else {
Log.e(IETSAFactory.TAG, "Permission denied for device(获取设备的权限被拒绝):\n" + usbDevice);
if (listener != null) {
listener.onUsbPermissionFail();
}
}
}
}
}
public void setListener(OnUsbPermissionListener listener) {
this.listener = listener;
}
public interface OnUsbPermissionListener {
/** 当USB权限获取失败回调 */
void onUsbPermissionFail();
/** 当权限通过回调 */
void onUsbPermissionAllow(UsbDevice usbDevice);
}
}
到此Android 串口和USB的通信开发完结。