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中打开查看。
如果有问题请自己留言,不要私信,你的问题可能也是别人的问题,谢谢!