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