android调用内置摄像头的方法相对比较简单,参考实例也比较多,但是针对调用外置摄像头的方法介绍比较少,本篇对现有的 资料进行汇总,并给出相关案例如下:
https://blog.csdn.net/fengshiguang2012/article/details/79569280
https://blog.csdn.net/andrexpert/article/details/78324181
https://blog.csdn.net/CrazyMo_/article/details/58139934
https://blog.csdn.net/qq_31939617/article/details/82348796
开源项目:
https://github.com/saki4510t/UVCCamera
https://github.com/jiangdongguo/AndroidUSBCamera
重点总结:
查找资料过程中,可以发现目前调用外置usb摄像头的方法基本上都是基于UVCCamera这个开源项目,原理是android设备具备otg功能,通过检测android设备是否有usb设备连接,进一步采集usb摄像头所采集到的图像数据。
// ********** 显示摄像头采集的图像结果 *************
private void startPreview() {
synchronized (mSync) {
if (mCameraHandler != null) {
final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
mCameraHandler.setPreviewCallback(mIFrameCallback);
mCameraHandler.startPreview(new Surface(st));
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
updateItems();
}
这里对图像的显示方法进行总结,图像显示主要有两种方法,一种是:
final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
mCameraHandler.startPreview(new Surface(st));
另外一种是:
mCameraHandler.setPreviewCallback(mIFrameCallback);
//*************** IFrameCallback ***************
private final IFrameCallback mIFrameCallback = new IFrameCallback() {
@Override
public void onFrame(final ByteBuffer frame) {
frame.clear();
if(!isActive() || isInCapturing){
return;
}
if(bitmap == null){
Toast.makeText(MainActivity.this, "错误:Bitmap为空", Toast.LENGTH_SHORT).show();
return;
}
synchronized (bitmap) {
srcBitmap.copyPixelsFromBuffer(frame);
WarnText = "";
if(bitmap.getWidth() != srcBitmap.getWidth() || bitmap.getHeight() != srcBitmap.getHeight()){
bitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.RGB_565);
}
Mat src = new Mat ();
Utils.bitmapToMat(srcBitmap,src);
calculate(srcBitmap.getNativeObjAddr(), mLeft, mTop, mWidth, mHeight);
Utils.matToBitmap(srcBitmap,bitmap);
}
mImageView.post(mUpdateImageTask);
}
};
调用opencv时,需注意在程序中加入:
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
其他,像usb 设备的连接,断开等,可以参见程序部分:
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:");
synchronized (mSync) {
if (mCameraHandler != null) {
mCameraHandler.open(ctrlBlock);
startPreview();
updateItems();
}
}
}
@Override
public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
if (DEBUG) Log.v(TAG, "onDisconnect:");
synchronized (mSync) {
if (mCameraHandler != null) {
queueEvent(new Runnable() {
@Override
public void run() {
try{
// maybe throw java.lang.IllegalStateException: already released
mCameraHandler.setPreviewCallback(null);
}
catch(Exception e){
e.printStackTrace();
}
mCameraHandler.close();
}
}, 0);
}
}
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) {
setCameraButton(false);
}
};
后期经过我的优化,已经做出具备图像实时处理功能的app。有类似需求者,可以联系我。