赞
踩
刚开始接到这个这个任务的时候,看了一下这款读卡器设备的参数(res232协议读卡器技术参数)
初步尝试,利用串口接收 :
1.依赖接入:
- //串口检测
- implementation 'com.github.licheedev:Android-SerialPort-API:2.0.0'
2.设置串口参数,打开串口接收:
- private SerialPort mSerialPort;
- protected OutputStream mOutputStream;
- private InputStream mInputStream;
-
-
-
- private void init_readuserid() {
- try {
- mSerialPort = SerialPort
- .newBuilder(new File("/dev/ttyS3"), 9600) // 串口地址地址,波特率
- .dataBits(8) // 数据位,默认8;可选值为5~8
- .parity(0) // 校验位;0:无校验位(NONE,默认);1:奇校验位(ODD);2:偶校验位(EVEN)
- .stopBits(1) // 停止位,默认1;1:1位停止位;2:2位停止位
- .build();
- mOutputStream = mSerialPort.getOutputStream();
- mInputStream = mSerialPort.getInputStream();
- //开启接收线程
- new ReadThread().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) {
- Log.i(TAG, "run: 输入为空");
- System.out.println("+strData+strData入为空");
- return;
- }
- size = mInputStream.read(buffer);
- if (size > 0) {
- String strData = ByteUtil.byteToStr(buffer, size);
- Log.i(TAG, "run: 输入的=" + strData);
- System.out.println("run: 输入为=" + strData);
- // onDataReceived(buffer, size);
- }
- } catch (IOException e) {
- e.printStackTrace();
- return;
- }
- }
-
- }
- }

到这里,不管我这边怎么用卡片去刷,数据是始终反馈,一开始找了很多方式来接收串口的测试方法,都不行,刚开始,还以为是usb 权限问题,我这边把文件清单添加了usb权限:
- <!--USB权限-->
- <uses-feature android:name="android.hardware.usb.host" />
调用: openUsbDevice() ,来检测usb 权限问题;
- /**
- * 获得 usb 权限
- */
- private void openUsbDevice() {
- //before open usb device
- //should try to get usb permission
- tryGetUsbPermission();
- }
-
- UsbManager mUsbManager;
- private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
-
- private void tryGetUsbPermission() {
- mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
-
- IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
- registerReceiver(mUsbPermissionActionReceiver, filter);
-
- PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
-
- //here do emulation to ask all connected usb device for permission
- for (final UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
- //add some conditional check if necessary
- //if(isWeCaredUsbDevice(usbDevice)){
- if (mUsbManager.hasPermission(usbDevice)) {
- //if has already got permission, just goto connect it
- //that means: user has choose yes for your previously popup window asking for grant perssion for this usb device
- //and also choose option: not ask again
- afterGetUsbPermission(usbDevice);
- } else {
- //this line will let android popup window, ask user whether to allow this app to have permission to operate this usb device
- mUsbManager.requestPermission(usbDevice, mPermissionIntent);
- }
- //}
- }
- }
-
-
- private void afterGetUsbPermission(UsbDevice usbDevice) {
- //call method to set up device communication
- //Toast.makeText(this, String.valueOf("Got permission for usb device: " + usbDevice), Toast.LENGTH_LONG).show();
- //Toast.makeText(this, String.valueOf("Found USB device: VID=" + usbDevice.getVendorId() + " PID=" + usbDevice.getProductId()), Toast.LENGTH_LONG).show();
-
- doYourOpenUsbDevice(usbDevice);
- }
-
- private void doYourOpenUsbDevice(UsbDevice usbDevice) {
- //now follow line will NOT show: User has not given permission to device UsbDevice
- UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice);
- //add your operation code here
- }
-
- private final BroadcastReceiver mUsbPermissionActionReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (ACTION_USB_PERMISSION.equals(action)) {
- synchronized (this) {
- UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
- if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
- //user choose YES for your previously popup window asking for grant perssion for this usb device
- if (null != usbDevice) {
- afterGetUsbPermission(usbDevice);
- }
- } else {
- //user choose NO for your previously popup window asking for grant perssion for this usb device
- Toast.makeText(context, String.valueOf("Permission denied for device" + usbDevice), Toast.LENGTH_LONG).show();
- }
- }
- }
- }
- };

还是没有数据接收到,我这边找了很多的usb调试工具,最多都只是检测能否正常打开指定的usb 串口名有没有权限,能正常打开也是收不到任何的数据,我就想,这样的方式是不行的,然后我这边找到一个强大的测试串口工具,这边做一下分享推荐
https://blog.csdn.net/xlazydog/article/details/99458381
我这边就下载了这位大佬写的测试串口调试工具,没想到,我这边可以正常读取到卡片数据回来,然后就改成了他推荐的一个开源的Android 驱动库:
https://github.com/mik3y/usb-serial-for-android
接下来就是,第二次测试,用这个驱动库来测试行不行了:
我这边as工具用的版本是(androidx):
- compileSdkVersion 29
- buildToolsVersion "29.0.2"
直接用依赖到我的项目是,报错的,集成不进去:
implementation 'com.github.mik3y:usb-serial-for-android:Tag'
只能去下载他提供的android测试模块了,再手动导进去了:
https://blog.csdn.net/helloworld19870427/article/details/93221649(参考手动导入过程)
这边就不做分享导入的过程了。直接上码:
1.还是坚持usb权限问题,不然的话,就算可以找到设备,也有可能打开失败(connection 为 null),用 //usb权限开启
openUsbDevice() 是可以避免失败的问题。
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
- private SerialInputOutputManager mSerialIoManager;
- private ExecutorService mExecutor;
- private UsbSerialPort port;
- private StringBuffer sBuffer;
- //usb-rs232
- // Find all available drivers from attached devices.
- //usb权限开启
- openUsbDevice();
-
- UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
- List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
- if (availableDrivers.isEmpty()) {
- return;
- }
- // Open a connection to the first available driver.
- UsbSerialDriver driver = availableDrivers.get(0);
- UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
- if (connection == null) {
- // You probably need to call UsbManager.requestPermission(driver.getDevice(), ..)
- return;
- }
- // Read some data! Most have just one port (port 0).
- port = driver.getPorts().get(0);
- try {
- port.open(connection);
- port.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
-
- byte buffer[] = new byte[16];
- int numBytesRead = port.read(buffer, 1000);
- Log.i(TAG, "Read= " + numBytesRead + " bytes.");
- } catch (IOException e) {
- // Deal with error.
- }
-
- sBuffer=new StringBuffer();
- mExecutor = Executors.newSingleThreadExecutor();
- mSerialIoManager = new SerialInputOutputManager(port, mListener);//添加监听
- // 在新的线程中监听串口的数据变化
- mExecutor.submit(mSerialIoManager);

收到读卡器返回的字节数据,这里有个问题是,这个依赖库的问题,他不是一次性完整的返回一整串数据,他的文档有使用说明是这样说的;
https://github.com/mik3y/usb-serial-for-android/wiki/Troubleshooting
- SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() {
- @Override
- public void onRunError(Exception e) {
- Log.i(TAG, "Runner stopped.");
- }
-
- @Override
- public void onNewData(final byte[] data) {
- //TODO 新的数据
- String usbid2 = bytesToHexString(data);
- Log.i(TAG, "新的数据data4=" + usbid2);
-
- Message message=handler.obtainMessage();
- message.what=3;
- message.obj=usbid2;
- handler.sendMessage(message);
-
- }
- };

我这边就处理方式也是死规定的,如果你那边的数据不一可以参考我下面的数据,处理方式(把字节数据 转 字符串拼接,每次的字符串的长度去清空,再次方便接收保存数据):
- public static String bytesToHexString(byte[] bytes) {
- String result = "";
- for (int i = 0; i < bytes.length; i++) {
- String hexString = Integer.toHexString(bytes[i] & 0xFF);
- if (hexString.length() == 1) {
- hexString = '0' + hexString;
- }
- result += hexString.toUpperCase();
- }
- return result;
- }
最后关闭
- @Override
- protected void onDestroy() {
- super.onDestroy();
- handler.removeCallbacksAndMessages(null);
-
- try {
- port.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
到这里就基本实现了一个读卡器正常接收卡片的信息,做个简单的记录,简单集成usb-serial-for-android驱动库,就测试好了,当然我这边是用的一个设备来测试,如果多个设备接收,我这边暂时没有实现,但关键是找到设备数,找到设备名,来相互确认名字,暂时是这样的思路,里面的文章还是有很多方式没有一一列举出来,可以自己尝试,如果你有更好的看法和实现方式,可以底部评论留下思路,可以一起交流学习。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。