@@ -9,12 +9,16 @@ import android.content.BroadcastReceiver
99import android.content.Context
1010import android.content.Intent
1111import android.content.IntentFilter
12+ import android.util.Log
1213import android.hardware.usb.UsbDevice
1314import android.hardware.usb.UsbManager
15+ import android.os.Build
1416import androidx.core.app.PendingIntentCompat
1517import androidx.core.content.ContextCompat
1618import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED
1719import kotlinx.coroutines.CompletableDeferred
20+ import java.util.Timer
21+ import java.util.TimerTask
1822
1923private val Context .usbPermissionCallbackAction
2024 get() = " $packageName .USB_PERMISSION_CALLBACK"
@@ -40,6 +44,10 @@ private object UsbDevicePermissionReceiver : BroadcastReceiver() {
4044 }
4145 }
4246
47+ fun isDeferred (device : UsbDevice ): Boolean = synchronized(this ) {
48+ return pendingRequests.containsKey(device)
49+ }
50+
4351 fun unregister (context : Context ) = synchronized(this ) {
4452 if (registered) {
4553 context.unregisterReceiver(this )
@@ -75,10 +83,39 @@ class UsbDevicePermissionManager(private val context: Context) {
7583 if (context.usbManager?.hasPermission(device) == true ) return true
7684 val res = CompletableDeferred <Boolean >()
7785 if (UsbDevicePermissionReceiver .addDeferred(device, res)) {
86+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
87+ Log .d(TAG , " PermissionReceiver added for ${device.productName} (${context.packageName} )" )
88+ }
7889 UsbDevicePermissionReceiver .register(context)
79- val intent = PendingIntentCompat .getBroadcast(context, 0 , Intent (context.usbPermissionCallbackAction).apply { `package` = context.packageName }, 0 , true )
80- context.usbManager?.requestPermission(device, intent)
90+ schedulePermissionRequest(device, 5 )
91+ } else {
92+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
93+ Log .d(TAG , " PermissionReceiver already added for ${device.productName} " )
94+ }
8195 }
96+ requestPermission(device)
8297 return res.await()
8398 }
99+
100+ // In case we couldn't ask for permission, retry every secondes, with a maximum of `maxRetries`
101+ private fun schedulePermissionRequest (device : UsbDevice , maxRetries : Int ) {
102+ if (maxRetries < 1 ) return
103+ Timer ().schedule(object : TimerTask () {
104+ override fun run () {
105+ if (UsbDevicePermissionReceiver .isDeferred(device)) {
106+ requestPermission(device)
107+ schedulePermissionRequest(device, maxRetries - 1 )
108+ }
109+ }
110+ }, 1000 )
111+ }
112+
113+ private fun requestPermission (device : UsbDevice ) {
114+ val intent = PendingIntentCompat .getBroadcast(context, 0 , Intent (context.usbPermissionCallbackAction).apply { `package` = context.packageName }, 0 , true )
115+ context.usbManager?.requestPermission(device, intent)
116+ }
117+
118+ companion object {
119+ private const val TAG = " UsbDevicePermissionMan"
120+ }
84121}
0 commit comments