接着上面的"uvc简单分析"的文章,
继续进行流程分析。
这里使用的是就是uvc提供的demo中的demo3,中的MainActivity。
这个类点击打开会弹出一个dialog,展示usb扫描到的usb设备,然后用户选择了某个usb设备,就会打开这个usb设备,如果是uvc的话。
那么这步是怎么起作用的呢,是因为CameraDialog中点击事件后有事件监听,如下所示,
private final DialogInterface.OnClickListener mOnDialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
final Object item = mSpinner.getSelectedItem();
if (item instanceof UsbDevice) {
mUSBMonitor.requestPermission((UsbDevice)item);
((CameraDialogParent)getActivity()).onDialogResult(false);
}
break;
case DialogInterface.BUTTON_NEGATIVE:
((CameraDialogParent)getActivity()).onDialogResult(true);
break;
}
}
};
可以看到这行:
mUSBMonitor.requestPermission((UsbDevice)item);
点进去可以看到
/**
* request permission to access to USB device
* @param device
* @return true if fail to request permission
*/
public synchronized boolean requestPermission(final UsbDevice device) {
boolean result = false;
if (isRegistered()) {
if (device != null) {
if (mUsbManager.hasPermission(device)) {
// call onConnect if app already has permission
processConnect(device);
} else {
。。。
}
} else {
。。。
}
} else {
。。。
}
return result;
}
其他代码我删除了,只留了一行
processConnect(device);
点进去,
/**
* open specific USB device
* @param device
*/
private final void processConnect(final UsbDevice device) {
if (destroyed) return;
updatePermission(device, true);
mAsyncHandler.post(new Runnable() {
@Override
public void run() {
if (DEBUG) Log.v(TAG, "processConnect:device=" + device);
UsbControlBlock ctrlBlock;
final boolean createNew;
ctrlBlock = mCtrlBlocks.get(device);
if (ctrlBlock == null) {
ctrlBlock = new UsbControlBlock(USBMonitor.this, device);
mCtrlBlocks.put(device, ctrlBlock);
createNew = true;
} else {
createNew = false;
}
if (mOnDeviceConnectListener != null) {
mOnDeviceConnectListener.onConnect(device, ctrlBlock, createNew);
}
}
});
}
可以看到
if (mOnDeviceConnectListener != null) { mOnDeviceConnectListener.onConnect(device, ctrlBlock, createNew); }
也就是回调了onConnect,那么这个回调listener是从哪里来的?
是从USBMonitor的构造方法中来的:
public USBMonitor(final Context context, final OnDeviceConnectListener listener) { 。。。 }
然后USBMonitor是在测试类MainActivity中定义的,
mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);
所以最终回调mOnDeviceConnectListener.onConnect,就回到了测试类MainActivity中的onConnect方法,如下所示:
private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
@Override
public void onAttach(final UsbDevice device) {
Toast.makeText(MainActivity.this, "USB_DEVICE_ATTACHED", Toast.LENGTH_SHORT).show();
}
@Override
public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
if (DEBUG) Log.v(TAG, "onConnect:");
mCameraHandler.open(ctrlBlock);
startPreview();
}
@Override
public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
if (DEBUG) Log.v(TAG, "onDisconnect:");
if (mCameraHandler != null) {
mCameraHandler.close();
setCameraButton(false);
}
}
@Override
public void onDettach(final UsbDevice device) {
Toast.makeText(MainActivity.this, "USB_DEVICE_DETACHED", Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel(final UsbDevice device) {
}
};
然后就开始执行下面两行:
mCameraHandler.open(ctrlBlock); startPreview();
第一行是连接usb设备,并获取usb摄像头数据,
第二行是展示预览页面,接收这个流数据。
所以如果有一个设备id,想直接连接,而不想弹出这个选择usb设备dialog的话,就可以在onAttach中将这个设备加入list中,然后直接调用下面这行代码即可:
mUSBMonitor.requestPermission(usbDevice);
这行代码最终执行的就是上面那两行代码。
示例如下:
if (usbDevice.getVendorId() == vid && usbDevice.getProductId() == pid){
mUSBMonitor.requestPermission(usbDevice);
}
当然可以加一个延时。