Search code examples
xamarinandroid-pendingintentusbserialandroid-14

Requesting USB Permission has been failed on Android 14, xamarin


I tried to gain a permission of USB device on Android 14 and Xamarin project. I used USBSerialForAndroid (https://github.com/anotherlab/UsbSerialForAndroid/)

Following lines are What I worked on.

        public static Task<bool> RequestPermissionAsync(this UsbManager manager, UsbDevice device, Context context)
        {
            var completionSource = new TaskCompletionSource<bool>();

            var usbPermissionReceiver = new UsbPermissionReceiver(completionSource);

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu)
                context.RegisterReceiver(usbPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION), (ActivityFlags)ReceiverFlags.Exported);
            else
                context.RegisterReceiver(usbPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION));
            

            // Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
            PendingIntentFlags pendingIntentFlags = Build.VERSION.SdkInt >= BuildVersionCodes.S && Build.VERSION.SdkInt < BuildVersionCodes.Tiramisu ? PendingIntentFlags.Mutable  : 0;

            var intent = PendingIntent.GetBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), pendingIntentFlags);

            manager.RequestPermission(device, intent);  

            return completionSource.Task;
        }

But When I set PendingIntentFlags to Mutable, Getting error,

Targeting U+ (version 34 and above) disallows creating or retrieving a PendingIntent with FLAG_MUTABLE, an implicit Intent within and without FLAG_NO_CREATE and FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for security reasons. To retrieve an already existing PendingIntent, use FLAG_NO_CREATE, however, to create a new PendingIntent with an implicit Intent use FLAG_IMMUTABLE.

I changed it Immutable, But I can't get the permission.

How can I solve this issue?

SOLVED

     public static Task<bool> RequestPermissionAsync_Another(this UsbManager manager, UsbDevice device, Context context)
    {
        TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
        UsbPermissionReceiver receiver = new UsbPermissionReceiver(taskCompletionSource);
        if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu)
            context.RegisterReceiver(receiver, new IntentFilter(ACTION_USB_PERMISSION), ReceiverFlags.Exported);
        else
            context.RegisterReceiver(receiver, new IntentFilter(ACTION_USB_PERMISSION));

        Intent intent = new Intent(ACTION_USB_PERMISSION);
        intent.SetPackage(context.PackageName);

        PendingIntent broadcast = PendingIntent.GetBroadcast(context, 0, intent, PendingIntentFlags.Mutable);
        manager.RequestPermission(device, broadcast);
        return taskCompletionSource.Task;
    }



Solution

  • Try explicit intent with mutable flag.

    Intent intent = new Intent(ACTION_USB_PERMISSION);
    intent.setPackage(getPackageName());
    pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_MUTABLE);
    

    https://developer.android.com/about/versions/14/behavior-changes-14#safer-intents