Android(安卓)AS下的OTG串口设备读写
Android AS下的OTG串口设备读写
- 新建工程
- 添加工具类
- 添加设备参数列表
- 具体实现
- WIFI adb
了解嵌入式的读者应该知道在单片机编程中串口(uart)通讯接口最常用的就是TTL和USB接口,将单片机TTL转USB就可以接入电脑查看串口数据实现电脑与单片机通讯,在Android AS下的NDK开发中讲解了Android使用TTL方式的接口收发数据,当然咱们常用的Android手机没有这样的接口,要实现手机和单片机串口通讯就可以用OTG来实现。
新建工程
添加工具类
在添加工具类时可能会有错误提示,只是包名错了,修改报错文件的包成自己当前工程的包名即可解决问题:
添加设备参数列表
在AndroidManifest中声明指定的USB设备,设备信息存放在resource="@xml/device_filter"
<intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>intent-filter><meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter"/>
xml文件夹下命名为device_filter.xml:
<?xml version="1.0" encoding="utf-8"?><resources> <!-- 0x0403 / 0x6001: FTDI FT232R UART --> <usb-device vendor-id="1027" product-id="24577" /> <!-- 0x0403 / 0x6015: FTDI FT231X --> <usb-device vendor-id="1027" product-id="24597" /> <!-- 0x2341 / Arduino --> <usb-device vendor-id="9025" /> <!-- 0x16C0 / 0x0483: Teensyduino --> <usb-device vendor-id="5824" product-id="1155" /> <!-- 0x10C4 / 0xEA60: CP210x UART Bridge --> <usb-device vendor-id="4292" product-id="60000" /> <!-- 0x067B / 0x2303: Prolific PL2303 --> <usb-device vendor-id="1659" product-id="8963" /></resources>
至于这个文件里面的数据表示的是什么,将USB转TTL模块插入电脑,在设备管理器里面可以看到:
PID_2303:2303的10进制是8963,也就是:product-id=“8963”
VID_067B:067B的10进制是1659,vendor-id=“1659”
不同的模块这两个值就不一样,所以就有了这样一个列表,当然这也不全,没有包含所有的型号。
具体实现
在MainActivity里面就可以写设备获取与数据收发了:
package com.example.otgdemo;import android.hardware.usb.UsbDevice;import android.hardware.usb.UsbManager;import android.os.AsyncTask;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.widget.Toast;import com.example.otgdemo.usbserial.driver.UsbSerialDriver;import com.example.otgdemo.usbserial.driver.UsbSerialProber;import com.example.otgdemo.usbserial.util.SerialInputOutputManager;import com.example.otgdemo.utils.LogUtils;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class MainActivity extends AppCompatActivity { private UsbManager mUsbManager; // usb设备管理 private List<DeviceEntry> mEntries; // 串口设备列表 private static UsbSerialDriver sDriver; // 打开的串口设备 private static SerialInputOutputManager mSerialIoManager; //数据发送、接收工具 private ExecutorService mExecutorService; //数据读取线程管理 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取USB_SERVICE的管理器 mUsbManager = (UsbManager)getSystemService(this.USB_SERVICE); mEntries = new ArrayList<>(); mExecutorService = Executors.newSingleThreadExecutor(); refreshDeviceList(); } /** * 刷新usb设备列表 */ private void refreshDeviceList() { new AsyncTask<Void, Void, List<DeviceEntry>>() { @Override protected List<DeviceEntry> doInBackground(Void... params) { Log.d("log","刷新设备列表 ..."); final List<DeviceEntry> result = new ArrayList<>(); Map<String, UsbDevice> deviceList = mUsbManager.getDeviceList(); if (deviceList.isEmpty()) { Log.d("log","设备列表为空"); } else { for (final UsbDevice device : mUsbManager.getDeviceList().values()) { final List<UsbSerialDriver> drivers = UsbSerialProber.probeSingleDevice(mUsbManager, device); Log.d("log","发现设备: " + device); if (drivers.isEmpty()) { Log.d("log"," - 空设备列表."); result.add(new DeviceEntry(null)); } else { for (UsbSerialDriver driver : drivers) { Log.d("log"," + " + driver); result.add(new DeviceEntry(driver)); } } } } return result; } @Override protected void onPostExecute(List<DeviceEntry> result) { if (result.isEmpty()) { Toast.makeText(MainActivity.this, "没发现可用设备!", Toast.LENGTH_SHORT).show(); return; } mEntries.clear(); mEntries.addAll(result); sDriver = mEntries.get(0).driver; reStart(); Log.d("log","停止刷新,发现" + mEntries.size() + " 个设备."); } }.execute((Void) null); } /** * 打开串口 */ private void reStart() { if (sDriver == null) { Toast.makeText(this, "没有发现串口设备.", Toast.LENGTH_SHORT).show(); } else { try { sDriver.open(); sDriver.setParameters(57600, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE); } catch (IOException e) { LogUtils.d("设备打开错误: " + e.getMessage(), e); Toast.makeText(this, "设备打开错误: " + e.getMessage(), Toast.LENGTH_SHORT).show(); try { sDriver.close(); } catch (IOException e2) { // Ignore. } sDriver = null; return; } Toast.makeText(this, " 串口设备: " + sDriver.getClass().getSimpleName(), Toast.LENGTH_SHORT).show(); } onDeviceStateChange(); } /** * 重置串口 */ private void onDeviceStateChange() { stopIoManager(); startIoManager(); } /** * 关闭串口 */ private void stopIoManager() { if (mSerialIoManager != null) { LogUtils.d("Stopping io manager .."); mSerialIoManager.stop(); mSerialIoManager = null; } } /** * 打开串口 */ private void startIoManager() { if (sDriver != null) { LogUtils.d("Starting io manager .."); mSerialIoManager = new SerialInputOutputManager(sDriver, mListener); mExecutorService.submit(mSerialIoManager);//开启数据读取线程 } } /** * Simple container for a UsbDevice and its driver. */ private static class DeviceEntry { public UsbSerialDriver driver; DeviceEntry(UsbSerialDriver driver) { this.driver = driver; } } /** * 数据读取回调 */ private final SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() { @Override public void onRunError(Exception e) { LogUtils.d("Runner stopped."); }// 数据接收的回调函数 @Override public void onNewData(byte[] data, int len) { } }; /** * 数据发送 * * @param data 要发送的数据 */ public static void sendData(byte[] data) { if (mSerialIoManager != null) { mSerialIoManager.writeAsync(data); } }}
WIFI adb
如果手机要调试那么会占用手机的usb端口,要下程序又要接OTG,来回拔插比较麻烦,可以在AS中使用wifi adb方式来部署应用。在file->seting->Plugins下选择下方中间一项:
右侧会有一个install的按钮,我之前安装过了就是这个样子:
安装完后会有这样一个图标:
在usb接到手机之后点击这个图标,出现如下,点击右侧的CONNECT即可:
变成这样就说明链接成功,就可以拔掉usb线了:
最新demo加入了CH340支持。
更多相关文章
- Android存储和加载本地文件(内部存储设备)
- Android(安卓)—— 注解(Annotation)也被称为元数据(Metadata)
- 理解 Android(安卓)本地数据存储 API
- 蓝牙防丢器原理、实现与Android(安卓)BLE接口编程
- 【Android】Android(安卓)BLE开发
- Android——开发环境简介
- Android获取手机设备信息并区分真机与模拟器
- 野人学Android基础篇之网络通讯第二课--本地apache服务器与Andro
- Android之sp和dip的区别