From 9092e8c9e041471f520f31c2d716f0f14b44d7fb Mon Sep 17 00:00:00 2001
From: Jiangdg <765067602@qq.com>
Date: Mon, 17 Jun 2019 15:26:32 +0800
Subject: [PATCH] supporting Android9.0 and fixing capture image failed
---
app/src/main/AndroidManifest.xml | 5 +-
.../usbcamera/application/MyApplication.java | 3 +-
.../jiangdg/usbcamera/utils/CrashHandler.java | 69 +++++-------------
.../usbcamera/view/SplashActivity.java | 2 +-
.../usbcamera/view/USBCameraActivity.java | 7 +-
app/src/main/res/values/strings.xml | 2 +-
build.gradle | 2 +-
.../jiangdg/usbcamera/UVCCameraHelper.java | 16 +++--
.../java/com/serenegiant/usb/USBMonitor.java | 72 ++++++++++++++++---
.../usb/common/AbstractUVCCameraHandler.java | 20 ++----
.../src/main/res/xml/device_filter.xml | 7 ++
11 files changed, 114 insertions(+), 91 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0c032c2..0e44b31 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,7 +3,10 @@
package="com.jiangdg.usbcamera">
-
+
+
+
+
mainActivityClass;
- // 用来存储设备信息和异常信息
private Map infos = new HashMap();
- /** 保证只有一个CrashHandler实例 */
+
private CrashHandler() {
}
- /** 获取CrashHandler实例 ,单例模式 */
public static CrashHandler getInstance() {
return instance;
}
@@ -56,22 +50,16 @@ public class CrashHandler implements UncaughtExceptionHandler {
public void init(Context context, Class> activityClass) {
mContext = context;
this.setMainActivityClass(activityClass);
- // 获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
- // 设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
- /**
- * 当UncaughtException发生时会转入该函数来处理
- */
+
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
- // 如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
- //重启应用,释放资源
System.out.println("uncaughtException--->" + ex.getMessage());
// Log.e(TAG, ex.getMessage());
logError(ex);
@@ -80,18 +68,10 @@ public class CrashHandler implements UncaughtExceptionHandler {
} catch (InterruptedException e) {
// Log.e("debug", "error:", e);
}
-// AppManagerUtils.removeAllActivities();
-// AppManagerUtils.restartApp(mContext,mContext.getPackageName());
-// AppManagerUtils.releaseAppResource();
+ exitApp();
}
}
- /**
- * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
- *
- * @param ex
- * @return true:如果处理了该异常信息;否则返回false.
- */
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
@@ -101,25 +81,20 @@ public class CrashHandler implements UncaughtExceptionHandler {
public void run() {
Looper.prepare();
Toast.makeText(mContext.getApplicationContext(),
- "unknown exception!Please checking logs in sd card.", Toast.LENGTH_LONG).show();
+ "unknown exception and exiting...Please checking logs in sd card!", Toast.LENGTH_LONG).show();
Looper.loop();
-
- android.os.Process.killProcess(android.os.Process.myPid());
- System.exit(0);
}
}).start();
- // 收集设备参数信息
collectDeviceInfo(mContext.getApplicationContext());
- // 保存日志文件
logError(ex);
return true;
}
- /**
- * 收集设备参数信息
- *
- * @param ctx
- */
+ private void exitApp() {
+ android.os.Process.killProcess(android.os.Process.myPid());
+ System.exit(0);
+ }
+
public void collectDeviceInfo(Context ctx) {
try {
PackageManager pm = ctx.getPackageManager();
@@ -133,7 +108,6 @@ public class CrashHandler implements UncaughtExceptionHandler {
infos.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
-// Log.e(TAG, "收集包信息出现错误", e);
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
@@ -141,25 +115,19 @@ public class CrashHandler implements UncaughtExceptionHandler {
field.setAccessible(true);
infos.put(field.getName(), field.get(null).toString());
} catch (Exception e) {
-// Log.e(TAG, "收集系统信息出现错误", e);
}
}
}
- /**
- * 保存错误信息到文件中
- *
- * @param ex
- * @return 返回文件名称,便于将文件传送到服务器
- */
+
private void logError(Throwable ex) {
StringBuffer sb = new StringBuffer();
-// for (Map.Entry entry : infos.entrySet()) {
-// String key = entry.getKey();
-// String value = entry.getValue();
-// sb.append(key + "=" + value + "\n");
-// }
+ for (Map.Entry entry : infos.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+ sb.append(key + "=" + value + "\n");
+ }
int num = ex.getStackTrace().length;
for (int i=0;i getMainActivityClass() {
diff --git a/app/src/main/java/com/jiangdg/usbcamera/view/SplashActivity.java b/app/src/main/java/com/jiangdg/usbcamera/view/SplashActivity.java
index 1887139..1214394 100644
--- a/app/src/main/java/com/jiangdg/usbcamera/view/SplashActivity.java
+++ b/app/src/main/java/com/jiangdg/usbcamera/view/SplashActivity.java
@@ -46,7 +46,7 @@ public class SplashActivity extends AppCompatActivity {
}
private boolean isVersionM() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
private void checkAndRequestPermissions() {
diff --git a/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java b/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java
index d76a0ac..5e527ec 100644
--- a/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java
+++ b/app/src/main/java/com/jiangdg/usbcamera/view/USBCameraActivity.java
@@ -35,6 +35,7 @@ import com.serenegiant.usb.common.AbstractUVCCameraHandler;
import com.serenegiant.usb.encoder.RecordParams;
import com.serenegiant.usb.widget.CameraViewInterface;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -147,7 +148,7 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
mCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
@Override
public void onPreviewResult(byte[] nv21Yuv) {
-
+ Log.d(TAG, "onPreviewResult: "+nv21Yuv.length);
}
});
}
@@ -227,7 +228,7 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
showShortMsg("sorry,camera open failed");
return super.onOptionsItemSelected(item);
}
- String picPath = UVCCameraHelper.ROOT_PATH + MyApplication.DIRECTORY_NAME +"images/"+ System.currentTimeMillis()
+ String picPath = UVCCameraHelper.ROOT_PATH + MyApplication.DIRECTORY_NAME +"/images/"+ System.currentTimeMillis()
+ UVCCameraHelper.SUFFIX_JPEG;
mCameraHelper.capturePicture(picPath, new AbstractUVCCameraHandler.OnCaptureListener() {
@Override
@@ -243,7 +244,7 @@ public class USBCameraActivity extends AppCompatActivity implements CameraDialog
return super.onOptionsItemSelected(item);
}
if (!mCameraHelper.isPushing()) {
- String videoPath = UVCCameraHelper.ROOT_PATH + MyApplication.DIRECTORY_NAME +"videos/"+ System.currentTimeMillis();
+ String videoPath = UVCCameraHelper.ROOT_PATH + MyApplication.DIRECTORY_NAME +"/videos/"+ System.currentTimeMillis();
FileUtils.createfile(FileUtils.ROOT_PATH + "test666.h264");
// if you want to record,please create RecordParams like this
RecordParams params = new RecordParams();
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 60b5af8..b68d7e4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,3 @@
- AndroidUSBCamera
+ USBCamera
diff --git a/build.gradle b/build.gradle
index 22ea390..d7e2a20 100644
--- a/build.gradle
+++ b/build.gradle
@@ -27,7 +27,7 @@ ext {
commonLibVersion= '2.12.4'
versionCompiler = 27
versionTarget = 27
- minSdkVersion = 23
+ minSdkVersion = 21
versionNameString = '1.0.0'
javaSourceCompatibility = JavaVersion.VERSION_1_8
javaTargetCompatibility = JavaVersion.VERSION_1_8
diff --git a/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java b/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java
index efe105a..20e20b7 100644
--- a/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java
+++ b/libusbcamera/src/main/java/com/jiangdg/usbcamera/UVCCameraHelper.java
@@ -32,9 +32,10 @@ public class UVCCameraHelper {
private static final String TAG = "UVCCameraHelper";
private int previewWidth = 640;
private int previewHeight = 480;
- // 高分辨率YUV格式帧率较低
public static final int FRAME_FORMAT_YUYV = UVCCamera.FRAME_FORMAT_YUYV;
- // 默认使用MJPEG
+ // Default using MJPEG
+ // if your device is connected,but have no images
+ // please try to change it to FRAME_FORMAT_YUYV
public static final int FRAME_FORMAT_MJPEG = UVCCamera.FRAME_FORMAT_MJPEG;
public static final int MODE_BRIGHTNESS = UVCCamera.PU_BRIGHTNESS;
public static final int MODE_CONTRAST = UVCCamera.PU_CONTRAST;
@@ -108,13 +109,13 @@ public class UVCCameraHelper {
new Thread(new Runnable() {
@Override
public void run() {
- // 休眠500ms,等待Camera创建完毕
+ // wait for camera created
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
- // 开启预览
+ // start previewing
startPreview(mCamView);
}
}).start();
@@ -172,13 +173,13 @@ public class UVCCameraHelper {
new Thread(new Runnable() {
@Override
public void run() {
- // 休眠500ms,等待Camera创建完毕
+ // wait for camera created
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
- // 开启预览
+ // start previewing
startPreview(mCamView);
}
}).start();
@@ -238,7 +239,8 @@ public class UVCCameraHelper {
.getDeviceFilters(mActivity.getApplicationContext(), R.xml.device_filter);
if (mUSBMonitor == null || deviceFilters == null)
return null;
- return mUSBMonitor.getDeviceList(deviceFilters.get(0));
+ // matching all of filter devices
+ return mUSBMonitor.getDeviceList(deviceFilters);
}
public void capturePicture(String savePath,AbstractUVCCameraHandler.OnCaptureListener listener) {
diff --git a/libusbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java b/libusbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java
index 5766184..c51e567 100644
--- a/libusbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java
+++ b/libusbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java
@@ -30,11 +30,14 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Build;
+import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
@@ -43,9 +46,15 @@ import android.util.SparseArray;
import com.serenegiant.utils.BuildCheck;
import com.serenegiant.utils.HandlerThreadHandler;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -298,24 +307,65 @@ public final class USBMonitor {
*/
public List getDeviceList(final List filters) throws IllegalStateException {
if (destroyed) throw new IllegalStateException("already destroyed");
+ // get detected devices
final HashMap deviceList = mUsbManager.getDeviceList();
+ // store those devices info before matching filter xml file
+ String fileName = Environment.getExternalStorageDirectory()+ "/USBCamera/failed_devices.txt";
+ File logFile = new File(fileName);
+ FileWriter fw = null;
+ PrintWriter pw = null;
final List result = new ArrayList();
- if (deviceList != null) {
- if ((filters == null) || filters.isEmpty()) {
- result.addAll(deviceList.values());
- } else {
- for (final UsbDevice device: deviceList.values() ) {
- for (final DeviceFilter filter: filters) {
- if ((filter != null) && filter.matches(device)) {
- // when filter matches
- if (!filter.isExclude) {
- result.add(device);
+ try {
+ fw = new FileWriter(logFile, true);
+ pw = new PrintWriter(fw);
+ if (deviceList != null) {
+ if ((filters == null) || filters.isEmpty()) {
+ result.addAll(deviceList.values());
+ } else {
+ for (final UsbDevice device: deviceList.values() ) {
+ // match devices
+ for (final DeviceFilter filter: filters) {
+ if ((filter != null) && filter.matches(device) || (filter != null && filter.mSubclass == device.getDeviceSubclass())) {
+ // when filter matches
+ if (!filter.isExclude) {
+ result.add(device);
+ }
+ break;
+ } else {
+ // collection failed dev's class and subclass
+ String devModel = android.os.Build.MODEL;
+ String devSystemVersion = android.os.Build.VERSION.RELEASE;
+ String devClass = String.valueOf(device.getDeviceClass());
+ String subClass = String.valueOf(device.getDeviceSubclass());
+ if(pw != null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(devModel);
+ sb.append("/");
+ sb.append(devSystemVersion);
+ sb.append(":");
+ sb.append("class="+devClass+", subclass="+subClass);
+ pw.println(sb.toString());
+ pw.flush();
+ fw.flush();
+ }
}
- break;
}
}
}
}
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (pw != null) {
+ pw.close();
+ }
+ if (fw != null) {
+ try {
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
return result;
}
diff --git a/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java b/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
index ee62f38..62f0a3e 100644
--- a/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
+++ b/libusbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
@@ -813,8 +813,6 @@ public abstract class AbstractUVCCameraHandler extends Handler {
saveYuv2Jpeg(picPath, yuv);
}
}).start();
-
- isCaptureStill = false;
}
// 视频
if (mH264Consumer != null) {
@@ -829,27 +827,23 @@ public abstract class AbstractUVCCameraHandler extends Handler {
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);
boolean result = yuvImage.compressToJpeg(new Rect(0, 0, mWidth, mHeight), 100, bos);
if (result) {
- byte[] buffer = bos.toByteArray();
- Bitmap bmp = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
+ byte[] buffer = bos.toByteArray();
File file = new File(path);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
+ // fixing bm is null bug instead of using BitmapFactory.decodeByteArray
+ fos.write(buffer);
+ fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
- }
- bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
- try {
- fos.flush();
- fos.close();
- bmp.recycle();
- if (mCaptureListener != null) {
- mCaptureListener.onCaptureResult(path);
- }
} catch (IOException e) {
e.printStackTrace();
}
+ if (mCaptureListener != null) {
+ mCaptureListener.onCaptureResult(path);
+ }
}
try {
bos.close();
diff --git a/libusbcamera/src/main/res/xml/device_filter.xml b/libusbcamera/src/main/res/xml/device_filter.xml
index da573ff..2ac246c 100644
--- a/libusbcamera/src/main/res/xml/device_filter.xml
+++ b/libusbcamera/src/main/res/xml/device_filter.xml
@@ -25,4 +25,11 @@
+
+
+
+
+
+
+