背景:近期公司一个项目对接第三方支付设备(类似平板的设备外接usb转串口设备),需要使用usb转串口,实现通信和交互,今天记下过程。
有引用这个库 https://github.com/mik3y/usb-serial-for-android,感谢开源的大佬。
这个库已经集合了一般的芯片协议,就不需要自己再配置了。我们设备是用的ProlificSerialDriver.
唯一要注意的是配置设备的参数:波特率,数据位,体制位,奇偶校验等。其中我就在奇偶校验的参数配置上坑了一把。
只需要按照流程,注意些细节就能跑。
贴下核心的几段代码:
import androID.harDWare.usb.UsbDeviceimport androID.harDWare.usb.UsbDeviceConnectionimport androID.harDWare.usb.UsbManagerimport com.hoho.androID.usbserial.driver.UsbSerialPortimport com.hoho.androID.usbserial.driver.UsbSerialProberclass ZYDataSource(){ var mUsbSeriaPortManager: USBSerialPortManager? = null private var usbDeviceConnection: UsbDeviceConnection? = null private var mDevice: UsbDevice? = null private var mUsbSerialPort: UsbSerialPort? = null private var usbPermissionReceiver: UsbPermissionReceiver? = null private var mUsbManager: UsbManager? = null /** * 初始化 */ overrIDe fun initCompletable(context: Context): Completable { return Completable.create() { mUsbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager //查找所有设备 val driversList = UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager) if (driversList == null || driversList.size == 0) { throw Exception("未找到设备") } //直接取第一个. mDevice = driversList.first().device if (!mUsbManager?.hasPermission(mDevice)!!) { usbPermissionReceiver = UsbPermissionReceiver() //申请权限 val intent = Intent(ACTION_DEVICE_PERMISSION) val mPermissionIntent = PendingIntent.getbroadcast(context, 0, intent, 0) val permissionFilter = IntentFilter(ACTION_DEVICE_PERMISSION) context.registerReceiver(usbPermissionReceiver, permissionFilter) mUsbManager?.requestPermission(mDevice, mPermissionIntent) } else { this.openDeviceConnection(device = mDevice!!) } it.onComplete() } } inner class UsbPermissionReceiver : broadcastReceiver() { overrIDe fun onReceive(p0: Context?, intent: Intent?) { val action = intent?.getAction() if (ACTION_DEVICE_PERMISSION.equals(action)) { synchronized(this) { val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE) openDeviceConnection(device) } } } } /** * 打开连接 */ fun openDeviceConnection(device: UsbDevice) { synchronized(this) { //授权成功,在这里进行打开设备 *** 作 val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager) if (availableDrivers.isEmpty()) { return } // Open a connection to the first available driver. val driver = availableDrivers[0] // Read some data! Most have just one port (port 0). mUsbSerialPort = driver.ports[0] try { mUsbSeriaPortManager = USBSerialPortManager(mUsbSerialPort!!) usbDeviceConnection = mUsbManager?.openDevice(device) mUsbSerialPort?.open(usbDeviceConnection) mUsbSerialPort?.setParameters(9600, 8, UsbSerialPort.StopBITS_1, UsbSerialPort.PARITY_EVEN) } catch (e: Exception) { XLog.tag(TAG).e(e.message) throw Exception("设备初始化失败") } } } /** * 实际通信调用方法-找卡 */ overrIDe fun searchCardSingle(requestData: ByteArray): Single<ByteArray> { return Single.just(requestData) .flatMap { data -> val command = USBSerialPortManager.Command(data, data.size) //通信 mUsbSeriaPortManager!!.execute(command) } .flatMap { Single.just(it.rxBytes) } }}
下面这个是USBSerialPortManager工具类
import com.hoho.androID.usbserial.driver.UsbSerialPortimport io.reactivex.Singleimport io.reactivex.schedulers.Schedulersclass USBSerialPortManager(private val usbSerialPort: UsbSerialPort, private val writeTimeout: Int = 100, private val readTimeout: Int = 50) { open class Command(val hex: String, var rxLength: Int = 0, var rx: String = "") { val bytes: ByteArray get() = hex.hexStringToByteArray() val rxBytes: ByteArray get() = rx.hexStringToByteArray() constructor(bytes: ByteArray, rxLength: Int) : this(bytes.toHex(), rxLength, "") } private fun runOnceSingle(command: Command, timeoutInMillis: Int = 2000): Single<Command> { return Single.create { XLog.tag(TAG).i("send data=${command.hex} to $usbSerialPort") val txBytes = command.hex.hexStringToByteArray() usbSerialPort.write(txBytes, writeTimeout) if (command.rxLength <= 0) { command.rx = "" it.onSuccess(command) return@create } var times = 0L val interval = 2L val bytes = ByteArray(command.rxLength) var totalLength = 0 while (totalLength < command.rxLength) { val bytesToRead = ByteArray(command.rxLength - totalLength) val n = usbSerialPort.read(bytesToRead, readTimeout) if (n > 0) { for (i in 0 until n) { bytes[totalLength + i] = bytesToRead[i] } totalLength += n } Thread.sleep(interval) times += interval if (times > timeoutInMillis) { XLog.tag(TAG).e("read data from $usbSerialPort timeout, expect ${command.rxLength} bytes") it.onError(Exception("read data from $usbSerialPort timeout, expect ${command.rxLength} bytes")) return@create } } command.rx = bytes.toHex() XLog.tag(TAG).i("recv data=${command.rx} from $usbSerialPort") it.onSuccess(command) } } fun execute(command: Command, retryTimes: Long = 0L): Single<Command> { return runOnceSingle(command).retry(retryTimes).subscribeOn(Schedulers.single()) } companion object { const val TAG = "USBSerialPortManager" }}
代码是kotlin语言,没有写注释,目前项目已上线。工具类基本可以通用。
总结以上是内存溢出为你收集整理的Android之USB转串口通信-基本流程全部内容,希望文章能够帮你解决Android之USB转串口通信-基本流程所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)