这可能是史上最简单的UBS摄像头教程了,全程不过200行代码。
附上Project GitHub地址
https://github.com/wechat-AmosCC/AndroidUSBCamera
1,在项目中导入楼主编的libusbcamera-release.aar
implementation (name:'libusbcamera-release',ext:'aar')
2,在项目中引入日本友人的
api("com.serenegiant:common:2.12.4") {
excludemodule:'support-v4'
}
3,在你的Android项目中开始愉快的使用吧
3.1 XML布局文件先添加
3.2 .java中
extends AppCompatActivityimplements CameraDialog.CameraDialogParent, CameraViewInterface.Callback
实现CameraDialog,和CameraViewInterface
3.3 使用
mUVCCameraView = findViewById(R.id.camera_view);
mUVCCameraView.setCallback(this);
mCameraHelper = UVCCameraHelper.getInstance();
mCameraHelper.setDefaultFrameFormat(UVCCameraHelper.FRAME_FORMAT_MJPEG);
mCameraHelper.initUSBMonitor(this,mUVCCameraView,listener);
mCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(byte[] nv21Yuv) {
}
});
3.4 项目要添加存储读写权限。
3.5 完整的class
package gittest.uvc.amos.codes.com.uvcgittest;
import android.Manifest;
import android.content.pm.PackageManager;
import android.hardware.usb.UsbDevice;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.amos.codes.uvc.FileUtils;
import com.amos.codes.uvc.UVCCameraHelper;
import com.serenegiant.usb.CameraDialog;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.common.AbstractUVCCameraHandler;
import com.serenegiant.usb.encoder.RecordParams;
import com.serenegiant.usb.widget.CameraViewInterface;
import java.util.ArrayList;
import java.util.List;
public class MainActivityextends AppCompatActivityimplements CameraDialog.CameraDialogParent, CameraViewInterface.Callback{
private ButtonbtnPhoto,btnStartRec,btnStopRec,btnRotate;
private UVCCameraHelpermCameraHelper;
private CameraViewInterfacemUVCCameraView;
private boolean isRequest;
private boolean isPreview;
private UVCCameraHelper.OnMyDevConnectListenerlistener =new UVCCameraHelper.OnMyDevConnectListener() {
@Override
public void onAttachDev(UsbDevice device) {
// request open permission
if (!isRequest) {
isRequest =true;
if (mCameraHelper !=null) {
mCameraHelper.requestPermission(0);
}
}
}
@Override
public void onDettachDev(UsbDevice device) {
// close camera
if (isRequest) {
isRequest =false;
mCameraHelper.closeCamera();
showShortMsg(device.getDeviceName() +" is out");
}
}
@Override
public void onConnectDev(UsbDevice device,boolean isConnected) {
if (!isConnected) {
showShortMsg("fail to connect,please check resolution params");
isPreview =false;
}else {
isPreview =true;
showShortMsg("connecting");
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2500);
}catch (InterruptedException e) {
e.printStackTrace();
}
Looper.prepare();
if(mCameraHelper !=null &&mCameraHelper.isCameraOpened()) {
}
Looper.loop();
}
}).start();
}
}
@Override
public void onDisConnectDev(UsbDevice device) {
showShortMsg("disconnecting");
}
};
String[]permissions =new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
ListmPermissionList =new ArrayList<>();
private static final int PERMISSION_REQUEST =1;
private void checkPermission() {
mPermissionList.clear();
//判断哪些权限未授予
for (int i =0; i
if (ContextCompat.checkSelfPermission(this,permissions[i]) != PackageManager.PERMISSION_GRANTED) {
mPermissionList.add(permissions[i]);
}
}
/**
* 判断是否为空
*/
if (mPermissionList.isEmpty()) {//未授予的权限为空,表示都授予了
}else {//请求权限方法
String[] permissions =mPermissionList.toArray(new String[mPermissionList.size()]);//将List转为数组
ActivityCompat.requestPermissions(this, permissions,PERMISSION_REQUEST);
}
}
/**
* 响应授权
* 这里不管用户是否拒绝,都进入首页,不再重复申请权限
*/
@Override
public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSION_REQUEST:
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
private void showShortMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initButtons();
checkPermission();
mUVCCameraView = findViewById(R.id.camera_view);
mUVCCameraView.setCallback(this);
mCameraHelper = UVCCameraHelper.getInstance();
mCameraHelper.setDefaultFrameFormat(UVCCameraHelper.FRAME_FORMAT_MJPEG);
mCameraHelper.initUSBMonitor(this,mUVCCameraView,listener);
mCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(byte[] nv21Yuv) {
}
});
}
@Override
protected void onStart() {
super.onStart();
// step.2 register USB event broadcast
if (mCameraHelper !=null) {
mCameraHelper.registerUSB();
}
}
private void initButtons()
{
btnPhoto=(Button)findViewById(R.id.btn_TakePhoto);
btnPhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mCameraHelper ==null || !mCameraHelper.isCameraOpened()) {
showShortMsg("sorry,camera open failed");
return;
}
String picPath ="/sdcard/iScopePro/" +"image/"+ System.currentTimeMillis()
+ UVCCameraHelper.SUFFIX_JPEG;
Log.e("AmosDemo","save picPath picPath:" + picPath);
mCameraHelper.capturePicture(picPath,new AbstractUVCCameraHandler.OnCaptureListener() {
@Override
public void onCaptureResult(String path) {
Log.e("AmosDemo","save path:" + path);
}
});
}
});
btnStartRec=(Button)findViewById(R.id.btn_Rec_Start);
btnStartRec.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mCameraHelper ==null || !mCameraHelper.isCameraOpened()) {
showShortMsg("sorry,camera open failed");
return;
}
if (!mCameraHelper.isPushing()) {
String videoPath ="/sdcard/iScopePro/" +"image/" + System.currentTimeMillis();
FileUtils.createfile(FileUtils.ROOT_PATH +"test666.h264");
// if you want to record,please create RecordParams like this
RecordParams params =new RecordParams();
params.setRecordPath(videoPath);
params.setRecordDuration(0);// 设置为0,不分割保存
// params.setVoiceClose(mSwitchVoice.isChecked()); // is close voice
params.setVoiceClose(true);
mCameraHelper.startPusher(params,new AbstractUVCCameraHandler.OnEncodeResultListener() {
@Override
public void onEncodeResult(byte[] data,int offset,int length,long timestamp,int type) {
// type = 1,h264 video stream
if (type ==1) {
FileUtils.putFileStream(data, offset, length);
}
// type = 0,aac audio stream
if (type ==0) {
}
}
@Override
public void onRecordResult(String videoPath) {
Log.e("AmosDemo","videoPath = " + videoPath);
}
});
showShortMsg("start record...");
}
}
});
btnStopRec=(Button)findViewById(R.id.btn_Rec_Stop);
btnStopRec.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FileUtils.releaseFile();
mCameraHelper.stopPusher();
showShortMsg("stop record...");
}
});
btnRotate=(Button)findViewById(R.id.btn_Rotate);
btnRotate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
}
@Override
public USBMonitor getUSBMonitor() {
return mCameraHelper.getUSBMonitor();
}
@Override
public void onDialogResult(boolean canceled) {
if (canceled) {
showShortMsg("取消操作");
}
}
public boolean isCameraOpened() {
return mCameraHelper.isCameraOpened();
}
@Override
public void onSurfaceCreated(CameraViewInterface view, Surface surface) {
if (!isPreview &&mCameraHelper.isCameraOpened()) {
mCameraHelper.startPreview(mUVCCameraView);
isPreview =true;
}
}
@Override
public void onSurfaceChanged(CameraViewInterface view, Surface surface,int width,int height) {
}
@Override
public void onSurfaceDestroy(CameraViewInterface view, Surface surface) {
if (isPreview &&mCameraHelper.isCameraOpened()) {
mCameraHelper.stopPreview();
isPreview =false;
}
}
}