Unity Android(安卓)Usb 通信
16lz
2021-01-26
Unity 监听安卓USB得插拔,以及数据通信(安卓是主)
因为不想通过Android 继承 Unity的activity这种方式实现(需要修改manifest)。
所以具体实现方式是在Unity的Update中获取所有usb设备,然后自己判断插拔。
usbManager=(UsbManager)context.getSystemService(Context.USB_SERVICE); public List GetUsbDevice() { List alldevice = new ArrayList<>(); HashMap deviceMap=usbManager.getDeviceList(); Iterator iterator=deviceMap.values().iterator(); while(iterator.hasNext()){ UsbDevice nowDevice=iterator.next(); alldevice.add(nowDevice); } return alldevice; }
这是获取所有设备的代码。设备可以通过pid和vid 判断,然后也可以获取到设备类型,具体可以参考Android UsbDevice这个类。
我做法是直接把UsbDevice这个类返回到了Unity,然后就可以在Unity中获取这些数据了。
要打开UsbDevice需要申请权限,每次插拔设备后,都要重新获取权限。获取权限的方式,就是弹窗提示用户授权
ACTION_USB_PERMISSION = context.getPackageName() + ".USB_PERMISSION"; private void GetPermission() { if(targetDevice == null) return; if (!usbManager.hasPermission(targetDevice)) { IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); context.registerReceiver(mUsbPermissionReceiver, filter); PendingIntent pi = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0); usbManager.requestPermission(targetDevice, pi); } else { usbDeviceInit(); } } private BroadcastReceiver mUsbPermissionReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); context.unregisterReceiver(mUsbPermissionReceiver); if (ACTION_USB_PERMISSION.equals(action)) { if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { //获得了usb使用权限 usbDeviceInit(); } else { callback.DeviceError(0); Close(); } } } };
有了权限后,就可以获取设备的UsbEndpoint,设备有UsbConstants.USB_DIR_OUT和UsbConstants.USB_DIR_IN,一个是发送,一个是接收
private void usbDeviceInit() { int interfaceCount = targetDevice.getInterfaceCount(); for (int i = 0; i < interfaceCount; i++) { usbInterface = targetDevice.getInterface(i); } if (usbInterface != null) { connection = usbManager.openDevice(targetDevice); if (connection != null) { if (connection.claimInterface(usbInterface, true)) { for (int j = 0; j < usbInterface.getEndpointCount(); j++) { UsbEndpoint endpoint = usbInterface.getEndpoint(j); if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) { outendpoint = endpoint; } else if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) { inendpoint = endpoint; } } } } } StartRecive(); } public byte[] GetMessage() { int inMax = inendpoint.getMaxPacketSize(); ByteBuffer byteBuffer = ByteBuffer.allocate(inMax); UsbRequest usbRequest = new UsbRequest(); usbRequest.initialize(connection, inendpoint); usbRequest.queue(byteBuffer, inMax); UsbRequest waitRequest = connection.requestWait(); if (waitRequest == usbRequest) { byte[] retData = byteBuffer.array(); return retData; } else if(waitRequest == null) { Close(); } return null; }public void SendMessage(byte[] data) { final byte[] _data = data; Thread thread = new Thread(new Runnable() { @Override public void run() { byte[] bytes = _data; if (outendpoint == null || connection == null) { callback.DeviceError(5); } UsbInterface intf = targetDevice.getInterface(0); UsbEndpoint endpoint = intf.getEndpoint(0); UsbDeviceConnection connection = usbManager.openDevice(targetDevice); connection.claimInterface(intf, forceClaim); int ret = connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); if (ret < 0) { callback.DeviceError(7); } } }); }
代码有部分截取,接收需要自己创建一个线程。
上面部分是Android端的,Unity端的获取数据和调用安卓的方式,可以参考我以前的文章。
上传的unitypacket中,安卓代码打包成了aar,可以自己在Androidstudio中打开查看。
如果有问题请自己留言,不要私信,你的问题可能也是别人的问题,谢谢!
更多相关文章
- Android权限系统(二):开机授予运行时权限
- Android设备有哪些分辨率
- make_ext4fs 文件权限控制
- 常用的Android常量
- Android7.1 Presentation双屏异显 DEMO 样例
- 阿里巴巴人脸离线活体识别Android
- Android网络数据JSON解析使用总结
- Ubuntu android adb 使用
- Android如何在初始化的时候获取加载的布局的宽高