How to grant USB permission so that my kiosk device doesn't ask confirmation dialog?

4.9k Views Asked by At

i'm creating kiosk application which need USB permissions. It's going to be added at AOSP image as system app on our device and it's device owner app.

Application controls external device via USB on HOST mode so how it can get USB permission by default so that user doesn't need to give to every time when USB device will be powered off. Tablet will be closed casing so user doesn't have access to usb port and device which it controlling.

So i want certain USB device to be trusted by default. How to achieve it? How i can bypass android usb host permission confirmation dialog for my application.

Can this method used??

Then i found out something about whitelisting the devices. Going to try it tomorrow if it could be viable solution.

2

There are 2 best solutions below

3
On

I have the same problem, in your AndroidManifest.xml in the Activity that use the Device write this

<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />

you also have to create a filter file in your xml resources, eg res/xml/device_filter:

 <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <usb-device vendor-id="26214" product-id="26214" />
    </resources>

you must not call mManager.requestPermission(device, mPermissionIntent), so you have to directly call mManager.openDevice(mDevice); and you can communicate normally without the need appear permission pop-up message.

1
On

Replying to

Managed to get intent-filter working. Problem is that when powering the tablet it will query from user permission to startup application. So i still get query once. Problem is that i have 2 USB devices and it gives permission to first one. – Jude

Sorry I cannot post a comment, but what I saw was requesting permission onCreate() was requesting only once. However requesting in onResume() worked well for multiple devices! I got multiple dialogs and further, the dialog count doesn't match with the log statements of permission granted as well. So for example, I will request permission for one camera device and one other device just once.

However, I get 2 dialogs for camera and 2 dialogs for the other device, and multiple logs statements every time I accepted. Like for 2 dialogs I got 4 permission granted statements, so it's kinda hard to tell what exactly is going on internally. And those messages are not consistent every time. Sometimes I got 4 messages for 2 dialogs and sometimes I got 3 or 5 messages.

But for your reference I will attach my code which is working perfectly and I can receive permission for both the devices I'm trying to work with,


    private static final String TAG = "BLH/USBTest";
    private static final String ACTION_USB_PERMISSION = "com.blhealthcare.example.USB_PERMISSION";
    private static final int CAM_USB_PERM_CODE = 4532;
    private static final int STETH_USB_PERM_CODE = 4533;
    UsbManager usbManager;
    UsbDevice camDevice;
    UsbDevice stethDevice;
    List<UsbInterface> camInterfaces = new ArrayList<>();
    List<UsbInterface> stethInterfaces = new ArrayList<>();

    private boolean camPermGranted = false;
    private boolean stethPermGranted = false;


    private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {

        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            int reqCode = intent.getIntExtra("requestCode", 0);
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (device != null) {
                            if (reqCode == CAM_USB_PERM_CODE) {
                                Log.d(TAG, "onReceive: Permission granted for Camera");
                                camPermGranted = true;
                            } else if (reqCode == STETH_USB_PERM_CODE) {
                                Log.d(TAG, "onReceive: Permission granted for Steth");
                                stethPermGranted = true;
                            }
                        }
                    } else {
                        Log.d(TAG, "Permission denied for device " + device);
                    }
                }
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        initializeUSBDevices();
        checkUSBInput();

    }

    // Helpers

    private void requestCamPerm(Context context) {
        Intent camIntent = new Intent(ACTION_USB_PERMISSION);
        camIntent.putExtra("requestCode", CAM_USB_PERM_CODE);
        PendingIntent camPermIntent = PendingIntent.getBroadcast(context, CAM_USB_PERM_CODE, camIntent, 0);
        usbManager.requestPermission(camDevice, camPermIntent);
    }

    private void requestStethPerm(Context context) {
        Intent stethIntent = new Intent(ACTION_USB_PERMISSION);
        stethIntent.putExtra("requestCode", STETH_USB_PERM_CODE);
        PendingIntent stethPermIntent = PendingIntent.getBroadcast(context, STETH_USB_PERM_CODE, stethIntent, 0);
        usbManager.requestPermission(stethDevice, stethPermIntent);
    }

    private void initializeUSBDevices() {
        String camvId = "4f2";
        String stethvId = "d8c";
        camDevice = getUsbDeviceFromVid(camvId);
        stethDevice = getUsbDeviceFromVid(stethvId);
    }

    private UsbDevice getUsbDeviceFromVid(String vid) {
        UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        if (usbManager != null) {
            for (UsbDevice d : usbManager.getDeviceList().values()) {
                if (Integer.toHexString(d.getVendorId()).equals(vid)) {
                    // Log.d(TAG, "USBDevices: Found Device VID: " + vid);
                    return d;
                }
            }
        }
        return null;
    }
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        registerReceiver(usbReceiver, filter);
        requestCamPerm(this);
        requestStethPerm(this);
    }

Oh and by the way, I haven't provided anything extra in the manifest, like vendorId etc. Just one thing,

<uses-feature android:name="android.hardware.usb.host"/>

EDIT* - Finally got it.

So like everyone has mentioned,

  1. Do not use USB Host API Call UsbManager.requestPermission()
  2. Create your device-filter via xml under resources and add that to meta-data in manifest. Must use INTEGER IDs only, no hex.
  3. Finally make sure your add this under your activity
android:directBootAware="true"

persists after reboot