Browse Source

重构项目,包括内存泄漏优化,分辨率切换,画面尺寸等

main
jiangdongguo 7 years ago
parent
commit
ebaab64809
  1. 4
      app/build.gradle
  2. 469
      app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java
  3. 88
      app/src/main/res/layout/activity_usbcamera.xml
  4. 9
      app/src/main/res/layout/layout_dialog_list.xml
  5. 20
      app/src/main/res/menu/main_toobar.xml
  6. 3
      app/src/main/res/values/colors.xml
  7. 2
      app/src/main/res/values/strings.xml
  8. 2
      app/src/main/res/values/styles.xml
  9. 2
      build.gradle
  10. 2
      libusbcamera/build.gradle
  11. 360
      libusbcamera/src/main/java/com/jiangdg/usbcamera/USBCameraManager.java
  12. 311
      libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java

4
app/build.gradle

@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "26.0.1"
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.jiangdg.usbcamera"
minSdkVersion 16
@ -28,5 +28,5 @@ dependencies {
testCompile 'junit:junit:4.12'
compile project(':libusbcamera')
compile 'com.jakewharton:butterknife:8.8.1'
compile 'com.jakewharton:butterknife-compiler:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

469
app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java

@ -1,17 +1,29 @@
package com.jiangdg.usbcamera.view;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.os.Bundle;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.widget.Button;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import com.jiangdg.usbcamera.utils.FileUtils;
import com.jiangdg.usbcamera.R;
import com.jiangdg.usbcamera.USBCameraManager;
import com.jiangdg.usbcamera.UVCCameraHelper;
import com.jiangdg.usbcamera.utils.FileUtils;
import com.serenegiant.usb.CameraDialog;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.USBMonitor;
@ -19,87 +31,92 @@ 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;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* AndroidUSBCamera引擎使用Demo
*
* UVCCamera use demo
* <p>
* Created by jiangdongguo on 2017/9/30.
*/
public class USBCameraActivity extends AppCompatActivity implements CameraDialog.CameraDialogParent{
public class USBCameraActivity extends AppCompatActivity implements CameraDialog.CameraDialogParent, CameraViewInterface.Callback {
@BindView(R.id.camera_view)
public View mTextureView;
@BindView(R.id.btn_capture_pic)
public Button mBtnCapture;
@BindView(R.id.btn_rec_video)
public Button mBtnRecord;
@BindView(R.id.btn_update_resolution)
public Button mBtnUpdateResultion;
@BindView(R.id.btn_restart_camera)
Button mBtnRestartCamera;
@BindView(R.id.btn_contrast)
Button mBtnContrast;
@BindView(R.id.btn_brightness)
Button mBtnBrightness;
private USBCameraManager mUSBManager;
@BindView(R.id.toolbar)
public Toolbar mToolbar;
@BindView(R.id.seekbar_brightness)
public SeekBar mSeekBrightness;
@BindView(R.id.seekbar_contrast)
public SeekBar mSeekContrast;
private UVCCameraHelper mCameraHelper;
private CameraViewInterface mUVCCameraView;
private AlertDialog mDialog;
private boolean isRequest;
private boolean isPreview;
/**
* USB设备事件监听器
* */
private USBCameraManager.OnMyDevConnectListener listener = new USBCameraManager.OnMyDevConnectListener() {
// 插入USB设备
private UVCCameraHelper.OnMyDevConnectListener listener = new UVCCameraHelper.OnMyDevConnectListener() {
@Override
public void onAttachDev(UsbDevice device) {
if(mUSBManager == null || mUSBManager.getUsbDeviceCount() == 0){
showShortMsg("未检测到USB摄像头设备");
if (mCameraHelper == null || mCameraHelper.getUsbDeviceCount() == 0) {
showShortMsg("check no usb camera");
return;
}
// 请求打开摄像头
if(! isRequest){
// request open permission
if (!isRequest) {
isRequest = true;
if(mUSBManager != null){
mUSBManager.requestPermission(0);
if (mCameraHelper != null) {
mCameraHelper.requestPermission(0);
}
}
}
// 拔出USB设备
@Override
public void onDettachDev(UsbDevice device) {
if(isRequest){
// 关闭摄像头
// close camera
if (isRequest) {
isRequest = false;
mUSBManager.closeCamera();
showShortMsg(device.getDeviceName()+"已拨出");
mCameraHelper.closeCamera();
showShortMsg(device.getDeviceName() + " is out");
}
}
// 连接USB设备成功
@Override
public void onConnectDev(UsbDevice device,boolean isConnected) {
if(! isConnected) {
showShortMsg("连接失败,请检查分辨率参数是否正确");
public void onConnectDev(UsbDevice device, boolean isConnected) {
if (!isConnected) {
showShortMsg("fail to connect,please check resolution params");
isPreview = false;
}else{
} else {
isPreview = true;
showShortMsg("connecting");
// initialize seekbar
// need to wait UVCCamera initialize over
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Looper.prepare();
mSeekBrightness.setProgress(mCameraHelper.getModelValue(UVCCameraHelper.MODE_BRIGHTNESS));
mSeekContrast.setProgress(mCameraHelper.getModelValue(UVCCameraHelper.MODE_CONTRAST));
Looper.loop();
}
}).start();
}
}
// 与USB设备断开连接
@Override
public void onDisConnectDev(UsbDevice device) {
showShortMsg("连接失败");
showShortMsg("disconnecting");
}
};
@ -108,150 +125,121 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_usbcamera);
ButterKnife.bind(this);
initView();
// step.1 initialize UVCCameraHelper
mUVCCameraView = (CameraViewInterface) mTextureView;
mUVCCameraView.setCallback(new CameraViewInterface.Callback() {
mUVCCameraView.setCallback(this);
mCameraHelper = UVCCameraHelper.getInstance();
mCameraHelper.initUSBMonitor(this, mUVCCameraView, listener);
}
private void initView() {
setSupportActionBar(mToolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
mSeekBrightness.setMax(100);
mSeekBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onSurfaceCreated(CameraViewInterface view, Surface surface) {
if(!isPreview && mUSBManager.isCameraOpened()) {
mUSBManager.startPreview(mUVCCameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mCameraHelper != null && mCameraHelper.isCameraOpened()) {
mCameraHelper.setModelValue(UVCCameraHelper.MODE_BRIGHTNESS,progress);
}
}
@Override
public void onPreviewResult(boolean result) {
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
isPreview = true;
mSeekContrast.setMax(100);
mSeekContrast.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mCameraHelper != null && mCameraHelper.isCameraOpened()) {
mCameraHelper.setModelValue(UVCCameraHelper.MODE_CONTRAST,progress);
}
}
@Override
public void onSurfaceChanged(CameraViewInterface view, Surface surface, int width, int height) {
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onSurfaceDestroy(CameraViewInterface view, Surface surface) {
if(isPreview && mUSBManager.isCameraOpened()) {
mUSBManager.stopPreview();
isPreview = false;
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// 初始化引擎
mUSBManager = USBCameraManager.getInstance();
mUSBManager.initUSBMonitor(this,listener);
mUSBManager.createUVCCamera(mUVCCameraView);
}
@Override
protected void onStart() {
super.onStart();
if(mUSBManager == null)
return;
// 注册USB事件广播监听器
mUSBManager.registerUSB();
mUVCCameraView.onResume();
// step.2 register USB event broadcast
if (mCameraHelper != null) {
mCameraHelper.registerUSB();
}
}
@Override
protected void onStop() {
super.onStop();
// 注销USB事件广播监听器
if(mUSBManager != null){
mUSBManager.unregisterUSB();
// step.3 unregister USB event broadcast
if (mCameraHelper != null) {
mCameraHelper.unregisterUSB();
}
mUVCCameraView.onPause();
}
@OnClick({ R.id.btn_contrast,R.id.btn_brightness,R.id.btn_capture_pic, R.id.btn_rec_video,R.id.btn_update_resolution,R.id.btn_restart_camera})
public void onViewClick(View view) {
int vId = view.getId();
switch (vId) {
// 对比度
case R.id.btn_contrast:
if(mUSBManager == null || !mUSBManager.isCameraOpened())
return;
int contrast = mUSBManager.getModelValue(USBCameraManager.MODE_CONTRAST);
mUSBManager.setModelValue(USBCameraManager.MODE_CONTRAST,contrast++);
break;
// 亮度
case R.id.btn_brightness:
if(mUSBManager == null || !mUSBManager.isCameraOpened())
return;
int brightness = mUSBManager.getModelValue(USBCameraManager.MODE_BRIGHTNESS);
mUSBManager.setModelValue(USBCameraManager.MODE_BRIGHTNESS,brightness++);
break;
// 重启Camera
case R.id.btn_restart_camera:
break;
// 切换分辨率
case R.id.btn_update_resolution:
if(mUSBManager == null || !mUSBManager.isCameraOpened())
return;
mUSBManager.updateResolution(320, 240, new USBCameraManager.OnPreviewListener() {
@Override
public void onPreviewResult(boolean isSuccess) {
if(! isSuccess) {
showShortMsg("预览失败,不支持该分辨率");
}else {
showShortMsg("以切换到分辨率为320x240");
}
}
});
break;
// 点击后自动对焦
case R.id.camera_view:
if(mUSBManager == null)
return;
// mUSBManager.startCameraFoucs();
// showShortMsg("对焦相机");
List<Size> list = mUSBManager.getSupportedPreviewSizes();
if(list == null) {
return;
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_toobar, menu);
return true;
}
StringBuilder sb = new StringBuilder();
for(Size size:list){
sb.append(size.width+"x"+size.height);
sb.append("\n");
}
showShortMsg(sb.toString());
break;
case R.id.btn_capture_pic:
if(mUSBManager == null || ! mUSBManager.isCameraOpened()){
showShortMsg("抓拍异常,摄像头未开启");
return;
}
String picPath = USBCameraManager.ROOT_PATH+System.currentTimeMillis()
+USBCameraManager.SUFFIX_PNG;
mUSBManager.capturePicture(picPath, new AbstractUVCCameraHandler.OnCaptureListener() {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_takepic:
if (mCameraHelper == null || !mCameraHelper.isCameraOpened()) {
showShortMsg("sorry,camera open failed");
return super.onOptionsItemSelected(item);
}
String picPath = UVCCameraHelper.ROOT_PATH + System.currentTimeMillis()
+ UVCCameraHelper.SUFFIX_PNG;
mCameraHelper.capturePicture(picPath, new AbstractUVCCameraHandler.OnCaptureListener() {
@Override
public void onCaptureResult(String path) {
showShortMsg("保存路径:"+path);
showShortMsg("save path:" + path);
}
});
break;
case R.id.btn_rec_video:
if(mUSBManager == null || ! mUSBManager.isCameraOpened()){
showShortMsg("录制异常,摄像头未开启");
return;
case R.id.menu_recording:
if (mCameraHelper == null || !mCameraHelper.isCameraOpened()) {
showShortMsg("sorry,camera open failed");
return super.onOptionsItemSelected(item);
}
if(! mUSBManager.isRecording()){
String videoPath = USBCameraManager.ROOT_PATH+System.currentTimeMillis();
FileUtils.createfile(FileUtils.ROOT_PATH+"test666.h264");
if (!mCameraHelper.isRecording()) {
String videoPath = UVCCameraHelper.ROOT_PATH + System.currentTimeMillis();
FileUtils.createfile(FileUtils.ROOT_PATH + "test666.h264");
RecordParams params = new RecordParams();
params.setRecordPath(videoPath);
params.setRecordDuration(0); // 设置为0,不分割保存
params.setVoiceClose(false); // 不屏蔽声音
mUSBManager.startRecording(params, new AbstractUVCCameraHandler.OnEncodeResultListener() {
mCameraHelper.startRecording(params, new AbstractUVCCameraHandler.OnEncodeResultListener() {
@Override
public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) {
// type = 0,aac格式音频流
// type = 1,h264格式视频流
if(type == 1){
FileUtils.putFileStream(data,offset,length);
// type = 0,aac stream
// type = 1,h264 stream
if (type == 1) {
FileUtils.putFileStream(data, offset, length);
}
}
@ -260,22 +248,171 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
showShortMsg(videoPath);
}
});
mBtnRecord.setText("正在录制");
showShortMsg("start record...");
} else {
FileUtils.releaseFile();
mUSBManager.stopRecording();
mBtnRecord.setText("开始录制");
mCameraHelper.stopRecording();
showShortMsg("stop record...");
}
break;
case R.id.menu_resolution:
showResolutionListDialog();
break;
case R.id.menu_focus:
if (mCameraHelper != null) {
mCameraHelper.startCameraFoucs();
}
break;
}
return super.onOptionsItemSelected(item);
}
private void showResolutionListDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(USBCameraActivity.this);
View rootView = LayoutInflater.from(USBCameraActivity.this).inflate(R.layout.layout_dialog_list, null);
ListView listView = (ListView) rootView.findViewById(R.id.listview_dialog);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(USBCameraActivity.this, android.R.layout.simple_list_item_1, getResolutionList());
if (adapter != null) {
listView.setAdapter(adapter);
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
if (mCameraHelper == null || !mCameraHelper.isCameraOpened())
return;
final String resolution = (String) adapterView.getItemAtPosition(position);
String[] tmp = resolution.split("x");
if (tmp != null && tmp.length >= 2) {
int widht = Integer.valueOf(tmp[0]);
int height = Integer.valueOf(tmp[1]);
mCameraHelper.updateResolution(widht, height, new UVCCameraHelper.OnPreviewListener() {
@Override
public void onPreviewResult(boolean isSuccess) {
if (isSuccess) {
showShortMsg("update resolution to " + resolution + " success");
}
}
});
}
mDialog.dismiss();
}
});
builder.setView(rootView);
mDialog = builder.create();
mDialog.show();
}
// example: {640x480,320x240,etc}
private List<String> getResolutionList() {
List<Size> list = mCameraHelper.getSupportedPreviewSizes();
List<String> resolutions = null;
if (list != null && list.size() != 0) {
resolutions = new ArrayList<>();
for (Size size : list) {
if (size != null) {
resolutions.add(size.width + "x" + size.height);
}
}
}
return resolutions;
}
// @OnClick({R.id.btn_contrast, R.id.btn_brightness, R.id.btn_capture_pic, R.id.btn_rec_video, R.id.btn_update_resolution, R.id.btn_restart_camera})
// public void onViewClick(View view) {
// int vId = view.getId();
// switch (vId) {
// case R.id.btn_contrast:
// if (mUSBManager == null || !mUSBManager.isCameraOpened())
// return;
// int contrast = mUSBManager.getModelValue(UVCCameraHelper.MODE_CONTRAST);
// mUSBManager.setModelValue(UVCCameraHelper.MODE_CONTRAST, contrast++);
// break;
// case R.id.btn_brightness:
// if (mUSBManager == null || !mUSBManager.isCameraOpened())
// return;
// int brightness = mUSBManager.getModelValue(UVCCameraHelper.MODE_BRIGHTNESS);
// mUSBManager.setModelValue(UVCCameraHelper.MODE_BRIGHTNESS, brightness++);
// break;
// case R.id.btn_update_resolution:
// break;
// case R.id.camera_view:
// if (mUSBManager == null)
// return;
//// mUSBManager.startCameraFoucs();
//// showShortMsg("对焦相机");
// List<Size> list = mUSBManager.getSupportedPreviewSizes();
// if (list == null) {
// return;
// }
//
// StringBuilder sb = new StringBuilder();
// for (Size size : list) {
// sb.append(size.width + "x" + size.height);
// sb.append("\n");
// }
// showShortMsg(sb.toString());
// break;
// case R.id.btn_capture_pic:
// if (mUSBManager == null || !mUSBManager.isCameraOpened()) {
// showShortMsg("抓拍异常,摄像头未开启");
// return;
// }
// String picPath = UVCCameraHelper.ROOT_PATH + System.currentTimeMillis()
// + UVCCameraHelper.SUFFIX_PNG;
// mUSBManager.capturePicture(picPath, new AbstractUVCCameraHandler.OnCaptureListener() {
// @Override
// public void onCaptureResult(String path) {
// showShortMsg("保存路径:" + path);
// }
// });
// break;
// case R.id.btn_rec_video:
// if (mUSBManager == null || !mUSBManager.isCameraOpened()) {
// showShortMsg("录制异常,摄像头未开启");
// return;
// }
//
// if (!mUSBManager.isRecording()) {
// String videoPath = UVCCameraHelper.ROOT_PATH + System.currentTimeMillis();
// FileUtils.createfile(FileUtils.ROOT_PATH + "test666.h264");
// RecordParams params = new RecordParams();
// params.setRecordPath(videoPath);
// params.setRecordDuration(0); // 设置为0,不分割保存
// params.setVoiceClose(false); // 不屏蔽声音
// mUSBManager.startRecording(params, new AbstractUVCCameraHandler.OnEncodeResultListener() {
// @Override
// public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) {
// // type = 0,aac格式音频流
// // type = 1,h264格式视频流
// if (type == 1) {
// FileUtils.putFileStream(data, offset, length);
// }
// }
//
// @Override
// public void onRecordResult(String videoPath) {
// showShortMsg(videoPath);
// }
// });
//
// mBtnRecord.setText("正在录制");
// } else {
// FileUtils.releaseFile();
// mUSBManager.stopRecording();
// mBtnRecord.setText("开始录制");
// }
// break;
// }
// }
@Override
protected void onDestroy() {
super.onDestroy();
if(mUSBManager != null){
mUSBManager.release();
// step.4 release uvc camera resources
if (mCameraHelper != null) {
mCameraHelper.release();
}
}
@ -285,17 +422,43 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
@Override
public USBMonitor getUSBMonitor() {
return mUSBManager.getUSBMonitor();
return mCameraHelper.getUSBMonitor();
}
@Override
public void onDialogResult(boolean canceled) {
if(canceled){
if (canceled) {
showShortMsg("取消操作");
}
}
public boolean isCameraOpened() {
return mUSBManager.isCameraOpened();
return mCameraHelper.isCameraOpened();
}
@Override
public void onSurfaceCreated(CameraViewInterface view, Surface surface) {
if (!isPreview && mCameraHelper.isCameraOpened()) {
mCameraHelper.startPreview(mUVCCameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean result) {
}
});
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;
}
}
}

88
app/src/main/res/layout/activity_usbcamera.xml

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -7,68 +8,73 @@
tools:context=".view.USBCameraActivity"
tools:ignore="MergeRootFrame">
<Button
android:id="@+id/btn_contrast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="对比度调整" />
<Button
android:id="@+id/btn_brightness"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="亮度调整" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:navigationIcon="@null"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<com.serenegiant.usb.widget.UVCCameraTextureView
android:id="@+id/camera_view"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
<Button
android:id="@+id/btn_capture_pic"
<LinearLayout
android:id="@+id/llayout_contrast"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="抓拍"
android:textSize="16sp" />
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<Button
android:id="@+id/btn_rec_video"
android:layout_width="match_parent"
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_above="@id/btn_capture_pic"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="开始录制"
android:textSize="16sp" />
android:paddingBottom="7dp"
android:paddingTop="7dp"
android:layout_weight="1"
android:textColor="@color/colorWhite"
android:text="对比度(contrast)" />
<SeekBar
android:id="@+id/seekbar_contrast"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent" />
</LinearLayout>
<Button
android:id="@+id/btn_update_resolution"
<LinearLayout
android:id="@+id/llayout_brightness"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/btn_rec_video"
android:layout_above="@id/llayout_contrast"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="切换分辨率为320x240"
android:textSize="16sp" />
android:orientation="horizontal">
<Button
android:id="@+id/btn_restart_camera"
android:layout_width="match_parent"
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_above="@id/btn_update_resolution"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="重启摄像头"
android:textSize="16sp" />
android:paddingBottom="7dp"
android:paddingTop="7dp"
android:layout_weight="1"
android:text="亮度(brightness)"
android:textColor="@color/colorWhite" />
<SeekBar
android:id="@+id/seekbar_brightness"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout>

9
app/src/main/res/layout/layout_dialog_list.xml

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listview_dialog"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

20
app/src/main/res/menu/main_toobar.xml

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_takepic"
android:title="takingPhotos(拍照)"
app:showAsAction="never" />
<item
android:id="@+id/menu_recording"
android:title="recording(录像)"
app:showAsAction="never" />
<item
android:id="@+id/menu_focus"
android:title="cameraFocus(对焦)"
app:showAsAction="never" />
<item
android:id="@+id/menu_resolution"
android:title="resolution(分辨率)"
app:showAsAction="never" />
</menu>

3
app/src/main/res/values/colors.xml

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimary">#303F9F</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="colorBlack">#000000</color>
<color name="colorWhite">#FFFFFF</color>
</resources>

2
app/src/main/res/values/strings.xml

@ -1,3 +1,3 @@
<resources>
<string name="app_name">AndroidUSBCamera</string>
<string name="app_name">UVCCamera</string>
</resources>

2
app/src/main/res/values/styles.xml

@ -1,7 +1,7 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>

2
build.gradle

@ -4,7 +4,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'com.android.tools.build:gradle:3.0.0'
}
}

2
libusbcamera/build.gradle

@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
android {
compileSdkVersion 25
buildToolsVersion "26.0.1"
buildToolsVersion '26.0.2'
defaultConfig {
minSdkVersion 16

360
libusbcamera/src/main/java/com/jiangdg/usbcamera/USBCameraManager.java

@ -1,360 +0,0 @@
package com.jiangdg.usbcamera;
import android.app.Activity;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.usb.UsbDevice;
import android.os.Environment;
import com.jiangdg.libusbcamera.R;
import com.serenegiant.usb.DeviceFilter;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.UVCCamera;
import com.serenegiant.usb.common.AbstractUVCCameraHandler;
import com.serenegiant.usb.common.UVCCameraHandler;
import com.serenegiant.usb.encoder.RecordParams;
import com.serenegiant.usb.widget.CameraViewInterface;
import java.io.File;
import java.util.List;
/**USB摄像头工具类
*
* Created by jiangdongguo on 2017/9/30.
*/
public class USBCameraManager{
public static final String ROOT_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator;
public static final String SUFFIX_PNG = ".png";
public static final String SUFFIX_MP4 = ".mp4";
private static final String TAG = "USBCameraManager";
private int previewWidth = 640;
private int previewHeight = 480;
public static int MODE_BRIGHTNESS = UVCCamera.PU_BRIGHTNESS;
public static int MODE_CONTRAST = UVCCamera.PU_CONTRAST;
// 使用MediaVideoBufferEncoder
private static final int ENCODER_TYPE = 2;
//0为YUYV,1为MJPEG
private static final int PREVIEW_FORMAT = 0;
private static USBCameraManager mUsbCamManager;
// USB设备管理类
private USBMonitor mUSBMonitor;
// Camera业务逻辑处理
private UVCCameraHandler mCameraHandler;
// 上下文
private Activity mActivity;
private USBMonitor.UsbControlBlock mCtrlBlock;
private CameraViewInterface cameraView;
private USBCameraManager(){}
public static USBCameraManager getInstance(){
if(mUsbCamManager == null){
mUsbCamManager = new USBCameraManager();
}
return mUsbCamManager;
}
public void closeCamera() {
if(mCameraHandler != null){
mCameraHandler.close();
}
}
public interface OnMyDevConnectListener{
void onAttachDev(UsbDevice device);
void onDettachDev(UsbDevice device);
void onConnectDev(UsbDevice device,boolean isConnected);
void onDisConnectDev(UsbDevice device);
}
public interface OnPreviewListener{
void onPreviewResult(boolean isSuccess);
}
/** 初始化
*
* context 上下文
* cameraView Camera要渲染的Surface
* listener USB设备检测与连接状态事件监听器
* */
public void initUSBMonitor(Activity activity,final OnMyDevConnectListener listener){
this.mActivity = activity;
mUSBMonitor = new USBMonitor(activity.getApplicationContext(), new USBMonitor.OnDeviceConnectListener() {
// 当检测到USB设备,被回调
@Override
public void onAttach(UsbDevice device) {
if(listener != null){
listener.onAttachDev(device);
}
}
// 当拨出或未检测到USB设备,被回调
@Override
public void onDettach(UsbDevice device) {
if(listener != null){
listener.onDettachDev(device);
}
}
// 当连接到USB Camera时,被回调
@Override
public void onConnect(final UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
mCtrlBlock = ctrlBlock;
// 打开摄像头
openCamera(ctrlBlock);
// 开启预览
startPreview(cameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean isConnected) {
if(listener != null){
listener.onConnectDev(device,isConnected);
}
}
});
}
// 当与USB Camera断开连接时,被回调
@Override
public void onDisconnect(UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock) {
if(listener != null){
listener.onDisConnectDev(device);
}
}
@Override
public void onCancel(UsbDevice device) {
}
});
}
public void createUVCCamera(CameraViewInterface cameraView) {
if(cameraView == null)
throw new NullPointerException("CameraViewInterface cannot be null!");
// 释放CameraHandler占用的相关资源
if(mCameraHandler != null){
mCameraHandler.release();
mCameraHandler = null;
}
// 重新初始化mCameraHandler
this.cameraView = cameraView;
cameraView.setAspectRatio(previewWidth / (float)previewHeight);
mCameraHandler = UVCCameraHandler.createHandler(mActivity,cameraView,ENCODER_TYPE,
previewWidth,previewHeight,PREVIEW_FORMAT);
}
// 切换分辨率
public void updateResolution(int width, int height, final OnPreviewListener mPreviewListener){
// 如果分辨率无变化,则无需重启Camera
if(previewWidth == width && previewHeight == height){
return;
}
this.previewWidth = width;
this.previewHeight = height;
// 释放CameraHandler占用的相关资源
if(mCameraHandler != null){
mCameraHandler.release();
mCameraHandler = null;
}
// 重新初始化mCameraHandler
cameraView.setAspectRatio(previewWidth / (float)previewHeight);
mCameraHandler = UVCCameraHandler.createHandler(mActivity,cameraView,ENCODER_TYPE,
previewWidth,previewHeight,PREVIEW_FORMAT);
openCamera(mCtrlBlock);
// 开始预览
startPreview(cameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean result) {
if(mPreviewListener != null){
mPreviewListener.onPreviewResult(result);
}
}
});
}
public void restartUSBCamera(CameraViewInterface cameraView,final OnPreviewListener mPreviewListener){
if(mCtrlBlock == null || cameraView == null)
throw new NullPointerException("mCtrlBlock or cameraView is null,please connected to camera");
// 创建Camera管理线程
createUVCCamera(cameraView);
// 创建Camera
openCamera(mCtrlBlock);
// 开始预览
startPreview(cameraView, new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean result) {
if(mPreviewListener != null){
mPreviewListener.onPreviewResult(result);
}
}
});
}
/**
* 注册检测USB设备广播接收器
* */
public void registerUSB(){
if(mUSBMonitor != null){
mUSBMonitor.register();
}
}
/**
* 注销检测USB设备广播接收器
*/
public void unregisterUSB(){
if(mUSBMonitor != null){
mUSBMonitor.unregister();
}
}
public boolean checkSupportFlag(final int flag) {
return mCameraHandler != null && mCameraHandler.checkSupportFlag(flag);
}
public int getModelValue(final int flag) {
return mCameraHandler != null ? mCameraHandler.getValue(flag) : 0;
}
public int setModelValue(final int flag, final int value) {
return mCameraHandler != null ? mCameraHandler.setValue(flag, value) : 0;
}
public int resetModelValue(final int flag) {
return mCameraHandler != null ? mCameraHandler.resetValue(flag) : 0;
}
/**
* 请求开启第index USB摄像头
*/
public void requestPermission(int index){
List<UsbDevice> devList = getUsbDeviceList();
if(devList==null || devList.size() ==0){
return;
}
int count = devList.size();
if(index >= count)
new IllegalArgumentException("index illegal,should be < devList.size()");
if(mUSBMonitor != null) {
mUSBMonitor.requestPermission(getUsbDeviceList().get(index));
}
}
// 返回USB设备列表数量
public int getUsbDeviceCount(){
List<UsbDevice> devList = getUsbDeviceList();
if(devList==null || devList.size() ==0){
return 0;
}
return devList.size();
}
// 返回USB设备列表
public List<UsbDevice> getUsbDeviceList(){
List<DeviceFilter> deviceFilters = DeviceFilter.getDeviceFilters(mActivity.getApplicationContext(), R.xml.device_filter);
if(mUSBMonitor == null || deviceFilters == null)
return null;
return mUSBMonitor.getDeviceList(deviceFilters.get(0));
}
// 拍照
public void capturePicture(String savePath,AbstractUVCCameraHandler.OnCaptureListener listener){
if(mCameraHandler != null && mCameraHandler.isOpened()){
mCameraHandler.captureStill(savePath,listener);
}
}
// 开始录像
public void startRecording(RecordParams params, AbstractUVCCameraHandler.OnEncodeResultListener listener){
if(mCameraHandler != null && ! isRecording()){
mCameraHandler.startRecording(params,listener);
}
}
// 停止录像
public void stopRecording(){
if(mCameraHandler != null && isRecording()){
mCameraHandler.stopRecording();
}
}
// 是否正在录像
public boolean isRecording(){
if(mCameraHandler != null){
return mCameraHandler.isRecording();
}
return false;
}
// 是否打开Camera
public boolean isCameraOpened(){
if(mCameraHandler != null){
return mCameraHandler.isOpened();
}
return false;
}
// 释放资源
public void release(){
//释放CameraHandler占用的相关资源
if(mCameraHandler != null){
mCameraHandler.release();
mCameraHandler = null;
}
// 释放USBMonitor占用的相关资源
if(mUSBMonitor != null){
mUSBMonitor.destroy();
mUSBMonitor = null;
}
}
public USBMonitor getUSBMonitor() {
return mUSBMonitor;
}
// 打开Camera
private void openCamera(USBMonitor.UsbControlBlock ctrlBlock) {
if(mCameraHandler != null){
mCameraHandler.open(ctrlBlock);
}
}
// 开始预览
public void startPreview(CameraViewInterface cameraView,AbstractUVCCameraHandler.OnPreViewResultListener mPreviewListener) {
SurfaceTexture st = cameraView.getSurfaceTexture();
if(mCameraHandler != null){
mCameraHandler.startPreview(st,mPreviewListener);
}
}
// 停止预览
public void stopPreview() {
if(mCameraHandler != null){
mCameraHandler.stopPreview();
}
}
// Camera对焦
public void startCameraFoucs(){
if(mCameraHandler != null){
mCameraHandler.startCameraFoucs();
}
}
// 获取Camera支持的所有分辨率参数
public List<Size> getSupportedPreviewSizes(){
if(mCameraHandler == null)
return null;
return mCameraHandler.getSupportedPreviewSizes();
}
}

311
libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java

@ -0,0 +1,311 @@
package com.jiangdg.usbcamera;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.usb.UsbDevice;
import android.os.Environment;
import com.jiangdg.libusbcamera.R;
import com.serenegiant.usb.DeviceFilter;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.UVCCamera;
import com.serenegiant.usb.common.AbstractUVCCameraHandler;
import com.serenegiant.usb.common.UVCCameraHandler;
import com.serenegiant.usb.encoder.RecordParams;
import com.serenegiant.usb.widget.CameraViewInterface;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.List;
/** UVCCamera Helper class
*
* Created by jiangdongguo on 2017/9/30.
*/
public class UVCCameraHelper {
public static final String ROOT_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator;
public static final String SUFFIX_PNG = ".png";
public static final String SUFFIX_MP4 = ".mp4";
private static final String TAG = "UVCCameraHelper";
private int previewWidth = 640;
private int previewHeight = 480;
public static int MODE_BRIGHTNESS = UVCCamera.PU_BRIGHTNESS;
public static int MODE_CONTRAST = UVCCamera.PU_CONTRAST;
//0-YUYV,1-MJPEG
private static final int PREVIEW_FORMAT = 0;
private static UVCCameraHelper mCameraHelper;
// USB Manager
private USBMonitor mUSBMonitor;
// Camera Handler
private UVCCameraHandler mCameraHandler;
private USBMonitor.UsbControlBlock mCtrlBlock;
private WeakReference<Activity> mActivityWrf;
private WeakReference<CameraViewInterface> mCamViewWrf;
private UVCCameraHelper() {
}
public static UVCCameraHelper getInstance() {
if (mCameraHelper == null) {
mCameraHelper = new UVCCameraHelper();
}
return mCameraHelper;
}
public void closeCamera() {
if (mCameraHandler != null) {
mCameraHandler.close();
}
}
public interface OnMyDevConnectListener {
void onAttachDev(UsbDevice device);
void onDettachDev(UsbDevice device);
void onConnectDev(UsbDevice device, boolean isConnected);
void onDisConnectDev(UsbDevice device);
}
public interface OnPreviewListener {
void onPreviewResult(boolean isSuccess);
}
public void initUSBMonitor(Activity activity, CameraViewInterface cameraView, final OnMyDevConnectListener listener) {
this.mActivityWrf = new WeakReference<>(activity);
this.mCamViewWrf = new WeakReference<>(cameraView);
mUSBMonitor = new USBMonitor(activity.getApplicationContext(), new USBMonitor.OnDeviceConnectListener() {
// called by checking usb device
// do request device permission
@Override
public void onAttach(UsbDevice device) {
if (listener != null) {
listener.onAttachDev(device);
}
}
// called by taking out usb device
// do close camera
@Override
public void onDettach(UsbDevice device) {
if (listener != null) {
listener.onDettachDev(device);
}
}
// called by connect to usb camera
// do open camera,start previewing
@Override
public void onConnect(final UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
mCtrlBlock = ctrlBlock;
openCamera(ctrlBlock);
startPreview(mCamViewWrf.get(), new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean isConnected) {
if (listener != null) {
listener.onConnectDev(device, isConnected);
}
}
});
}
// called by disconnect to usb camera
// do nothing
@Override
public void onDisconnect(UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock) {
if (listener != null) {
listener.onDisConnectDev(device);
}
}
@Override
public void onCancel(UsbDevice device) {
}
});
createUVCCamera();
}
public void createUVCCamera() {
if (mCamViewWrf.get() == null)
throw new NullPointerException("CameraViewInterface cannot be null!");
// release resources for initializing camera handler
if (mCameraHandler != null) {
mCameraHandler.release();
mCameraHandler = null;
}
// initialize camera handler
// cameraView.setAspectRatio(previewWidth / (float)previewHeight);
mCameraHandler = UVCCameraHandler.createHandler(mActivityWrf.get(), mCamViewWrf.get(), 2,
previewWidth, previewHeight, PREVIEW_FORMAT);
}
public void updateResolution(int width, int height, final OnPreviewListener mPreviewListener) {
if (previewWidth == width && previewHeight == height) {
return;
}
this.previewWidth = width;
this.previewHeight = height;
if (mCameraHandler != null) {
mCameraHandler.release();
mCameraHandler = null;
}
// cameraView.setAspectRatio(previewWidth / (float)previewHeight);
mCameraHandler = UVCCameraHandler.createHandler(mActivityWrf.get(), mCamViewWrf.get(), 2,
previewWidth, previewHeight, PREVIEW_FORMAT);
openCamera(mCtrlBlock);
startPreview(mCamViewWrf.get(), new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(boolean result) {
if (mPreviewListener != null) {
mPreviewListener.onPreviewResult(result);
}
}
});
}
public void registerUSB() {
if (mUSBMonitor != null) {
mUSBMonitor.register();
}
}
public void unregisterUSB() {
if (mUSBMonitor != null) {
mUSBMonitor.unregister();
}
}
public boolean checkSupportFlag(final int flag) {
return mCameraHandler != null && mCameraHandler.checkSupportFlag(flag);
}
public int getModelValue(final int flag) {
return mCameraHandler != null ? mCameraHandler.getValue(flag) : 0;
}
public int setModelValue(final int flag, final int value) {
return mCameraHandler != null ? mCameraHandler.setValue(flag, value) : 0;
}
public int resetModelValue(final int flag) {
return mCameraHandler != null ? mCameraHandler.resetValue(flag) : 0;
}
public void requestPermission(int index) {
List<UsbDevice> devList = getUsbDeviceList();
if (devList == null || devList.size() == 0) {
return;
}
int count = devList.size();
if (index >= count)
new IllegalArgumentException("index illegal,should be < devList.size()");
if (mUSBMonitor != null) {
mUSBMonitor.requestPermission(getUsbDeviceList().get(index));
}
}
public int getUsbDeviceCount() {
List<UsbDevice> devList = getUsbDeviceList();
if (devList == null || devList.size() == 0) {
return 0;
}
return devList.size();
}
public List<UsbDevice> getUsbDeviceList() {
List<DeviceFilter> deviceFilters = DeviceFilter
.getDeviceFilters(mActivityWrf.get().getApplicationContext(), R.xml.device_filter);
if (mUSBMonitor == null || deviceFilters == null)
return null;
return mUSBMonitor.getDeviceList(deviceFilters.get(0));
}
public void capturePicture(String savePath, AbstractUVCCameraHandler.OnCaptureListener listener) {
if (mCameraHandler != null && mCameraHandler.isOpened()) {
mCameraHandler.captureStill(savePath, listener);
}
}
public void startRecording(RecordParams params, AbstractUVCCameraHandler.OnEncodeResultListener listener) {
if (mCameraHandler != null && !isRecording()) {
mCameraHandler.startRecording(params, listener);
}
}
public void stopRecording() {
if (mCameraHandler != null && isRecording()) {
mCameraHandler.stopRecording();
}
}
public boolean isRecording() {
if (mCameraHandler != null) {
return mCameraHandler.isRecording();
}
return false;
}
public boolean isCameraOpened() {
if (mCameraHandler != null) {
return mCameraHandler.isOpened();
}
return false;
}
public void release() {
mCamViewWrf.clear();
mActivityWrf.clear();
if (mCameraHandler != null) {
mCameraHandler.release();
mCameraHandler = null;
}
if (mUSBMonitor != null) {
mUSBMonitor.destroy();
mUSBMonitor = null;
}
}
public USBMonitor getUSBMonitor() {
return mUSBMonitor;
}
private void openCamera(USBMonitor.UsbControlBlock ctrlBlock) {
if (mCameraHandler != null) {
mCameraHandler.open(ctrlBlock);
}
}
public void startPreview(CameraViewInterface cameraView, AbstractUVCCameraHandler.OnPreViewResultListener mPreviewListener) {
SurfaceTexture st = cameraView.getSurfaceTexture();
if (mCameraHandler != null) {
mCameraHandler.startPreview(st, mPreviewListener);
}
}
public void stopPreview() {
if (mCameraHandler != null) {
mCameraHandler.stopPreview();
}
}
public void startCameraFoucs() {
if (mCameraHandler != null) {
mCameraHandler.startCameraFoucs();
}
}
public List<Size> getSupportedPreviewSizes() {
if (mCameraHandler == null)
return null;
return mCameraHandler.getSupportedPreviewSizes();
}
}
Loading…
Cancel
Save