diff --git a/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/AndroidManifest.xml b/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/AndroidManifest.xml
index f7eb118751..f357826050 100644
--- a/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/AndroidManifest.xml
+++ b/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/AndroidManifest.xml
@@ -5,7 +5,7 @@
-
+
-
-
-
diff --git a/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/java/org/deviceconnect/android/deviceplugin/uvc/UVCDeviceService.java b/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/java/org/deviceconnect/android/deviceplugin/uvc/UVCDeviceService.java
index a9f9be4db5..af4570ce1f 100644
--- a/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/java/org/deviceconnect/android/deviceplugin/uvc/UVCDeviceService.java
+++ b/dConnectDevicePlugin/dConnectDeviceUVC/app/src/main/java/org/deviceconnect/android/deviceplugin/uvc/UVCDeviceService.java
@@ -7,6 +7,18 @@
package org.deviceconnect.android.deviceplugin.uvc;
+import android.Manifest;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbManager;
+import android.os.Handler;
+import android.os.Looper;
+
+import androidx.annotation.NonNull;
+
+import org.deviceconnect.android.activity.PermissionUtility;
import org.deviceconnect.android.deviceplugin.uvc.activity.ErrorDialogActivity;
import org.deviceconnect.android.deviceplugin.uvc.core.UVCDevice;
import org.deviceconnect.android.deviceplugin.uvc.core.UVCDeviceManager;
@@ -29,14 +41,34 @@ public class UVCDeviceService extends DConnectMessageService {
private UVCDeviceManager mDeviceMgr;
+ private BroadcastReceiver mPermissionReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ PermissionUtility.requestPermissions(context,
+ new Handler(Looper.getMainLooper()),
+ new String[]{Manifest.permission.CAMERA},
+ new PermissionUtility.PermissionRequestCallback() {
+
+ @Override
+ public void onSuccess() {
+ mDeviceMgr = ((UVCDeviceApplication) getApplication()).getDeviceManager();
+ mDeviceMgr.addDeviceListener(mDeviceListener);
+ mDeviceMgr.addConnectionListener(mConnectionListener);
+ mDeviceMgr.start();
+ }
+
+ @Override
+ public void onFail(@NonNull String s) {
+
+ }
+ });
+ }
+ };
@Override
public void onCreate() {
super.onCreate();
+ registerReceiver(mPermissionReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
- mDeviceMgr = ((UVCDeviceApplication) getApplication()).getDeviceManager();
- mDeviceMgr.addDeviceListener(mDeviceListener);
- mDeviceMgr.addConnectionListener(mConnectionListener);
- mDeviceMgr.start();
}
@Override
@@ -49,6 +81,7 @@ public void onDestroy() {
mDeviceMgr.removeDeviceListener(mDeviceListener);
mDeviceMgr.removeConnectionListener(mConnectionListener);
mDeviceMgr.stop();
+ unregisterReceiver(mPermissionReceiver);
super.onDestroy();
}
@@ -74,7 +107,21 @@ protected void onDevicePluginReset() {
if (BuildConfig.DEBUG) {
mLogger.info("Plug-in : onDevicePluginReset");
}
- resetPluginResource();
+ PermissionUtility.requestPermissions(this,
+ new Handler(Looper.getMainLooper()),
+ new String[]{Manifest.permission.CAMERA},
+ new PermissionUtility.PermissionRequestCallback() {
+
+ @Override
+ public void onSuccess() {
+ resetPluginResource();
+ }
+
+ @Override
+ public void onFail(@NonNull String s) {
+
+ }
+ });
}
@Override
diff --git a/dConnectDevicePlugin/dConnectDeviceUVC/libuvccamera/src/main/java/com/serenegiant/usb/USBMonitor.java b/dConnectDevicePlugin/dConnectDeviceUVC/libuvccamera/src/main/java/com/serenegiant/usb/USBMonitor.java
index 722dd3613b..936029feb4 100755
--- a/dConnectDevicePlugin/dConnectDeviceUVC/libuvccamera/src/main/java/com/serenegiant/usb/USBMonitor.java
+++ b/dConnectDevicePlugin/dConnectDeviceUVC/libuvccamera/src/main/java/com/serenegiant/usb/USBMonitor.java
@@ -33,6 +33,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import android.Manifest;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -44,13 +45,17 @@
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Handler;
+import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import androidx.annotation.NonNull;
+
import com.serenegiant.utils.BuildCheck;
import com.serenegiant.utils.HandlerThreadHandler;
+
public final class USBMonitor {
private static final boolean DEBUG = false; // TODO set false on production
@@ -384,7 +389,7 @@ public final void dumpDevices() {
* @return true: 指定したUsbDeviceにパーミッションがある
* @throws IllegalStateException
*/
- public final boolean hasPermission(final UsbDevice device) throws IllegalStateException {
+ public final boolean hasPermission(final UsbDevice device) throws IllegalStateException, SecurityException {
if (destroyed) throw new IllegalStateException("already destroyed");
return updatePermission(device, device != null && mUsbManager.hasPermission(device));
}
@@ -474,17 +479,21 @@ public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
// when received the result of requesting USB permission
- synchronized (USBMonitor.this) {
- final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
- if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
- if (device != null) {
- // get permission, call onConnect
- processConnect(device);
+ try {
+ synchronized (USBMonitor.this) {
+ final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
+ if (device != null) {
+ // get permission, call onConnect
+ processConnect(device);
+ }
+ } else {
+ // failed to get permission
+ processCancel(device);
}
- } else {
- // failed to get permission
- processCancel(device);
}
+ } catch (SecurityException e ) {
+ // ignore
}
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
@@ -522,8 +531,12 @@ public void run() {
synchronized (mHasPermissions) {
hasPermissionCounts = mHasPermissions.size();
mHasPermissions.clear();
- for (final UsbDevice device: devices) {
- hasPermission(device);
+ try {
+ for (final UsbDevice device : devices) {
+ hasPermission(device);
+ }
+ } catch (SecurityException e) {
+ // ignore
}
m = mHasPermissions.size();
}
@@ -551,6 +564,7 @@ public void run() {
*/
private final void processConnect(final UsbDevice device) {
if (destroyed) return;
+
updatePermission(device, true);
mAsyncHandler.post(new Runnable() {
@Override
@@ -646,7 +660,8 @@ public static final String getDeviceKeyName(final UsbDevice device, final boolea
* @return
*/
@SuppressLint("NewApi")
- public static final String getDeviceKeyName(final UsbDevice device, final String serial, final boolean useNewAPI) {
+ public static final String getDeviceKeyName(final UsbDevice device, final String serial, final boolean useNewAPI)
+ throws SecurityException {
if (device == null) return "";
final StringBuilder sb = new StringBuilder();
sb.append(device.getVendorId()); sb.append("#"); // API >= 12