Search code examples
androidusbadk

Remove USB Accessory permission dialog


I am working on an application which uses USB accessory.When I attach device to arduino it asks for usb permission and it has checkbox in dialog "use by default".When I checked and press ok then it should save permission and do not ask me again but it is asking for permission every time I attach USB.I want to save permission is there any way to save this?

My Code loooks like

@Override
public void onResume() {
    super.onResume();

    if (mInputStream != null && mOutputStream != null) {
        // streams were not null");
        return;
    }
    // streams were null");
    UsbAccessory[] accessories = mUsbManager.getAccessoryList();
    UsbAccessory accessory = (accessories == null ? null : accessories[0]);
    if (accessory != null) {
        if (mUsbManager.hasPermission(accessory)) {
            openAccessory(accessory);
        } else {
            synchronized (mUsbReceiver) {
                if (!mPermissionRequestPending) {
                    mUsbManager.requestPermission(accessory,
                            mPermissionIntent);
                    mPermissionRequestPending = true;
                }
            }
        }
    }

And Android manifest file looks

 <activity
        android:name="pkg.sarvajal.soochakdroid.Main"
        android:label="@string/Home" 
        android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
        android:screenOrientation="landscape">
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
             <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
        </intent-filter>


        <meta-data
            android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
            android:resource="@xml/accessory_filter" />
    </activity>

Accessory filter is like

<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory manufacturer="Manufacturer" model="Model" version="1.0" />
<usb-device vendor-id="0x0403" product-id="0x0403" />
</resources>

My BroadcastReceiver code

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                //UsbAccessory accessory = UsbManager.getAccessory(intent);
                UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                if (intent.getBooleanExtra(
                        UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    Flag_USB_Attached = true;
                    Flag_Count_USB_Attached = 0;
                    Flag_Count_USB_Restart_App = 0;
                    openAccessory(accessory);
                    String strdatetime =responce_date();
                    //sendSMS_background(phoneNumber, "USB Cable Connected  at "+strdatetime);


                } else {
                    // USB permission denied
                }
            }
        } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
            //UsbAccessory accessory = UsbManager.getAccessory(intent);
            UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
            if (accessory != null && accessory.equals(mAccessory)) {
                // accessory detached
                Flag_USB_Attached = false;
                Flag_Count_USB_Attached = 0;
                closeAccessory();
                String strdatetime =responce_date();
                //sendSMS_background(phoneNumber, "Communication Stopped! \n USB Cable Disconnected  at "+strdatetime);
                //SMS_USB();

            }
        }
}

And Settingup accessory code

/ Setting up accessory
private void setupAccessory() {
    //mUsbManager = UsbManager.getInstance(this);
    mUsbManager  = (UsbManager) getSystemService(Context.USB_SERVICE);
    mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
            ACTION_USB_PERMISSION), 0);
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
    registerReceiver(mUsbReceiver, filter);
    if (getLastNonConfigurationInstance() != null) {
        mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
        openAccessory(mAccessory);
    }
}
// Opening Accessory Mode
private void openAccessory(UsbAccessory accessory) {
    mFileDescriptor = mUsbManager.openAccessory(accessory);
    if (mFileDescriptor != null) {
        mAccessory = accessory;
        FileDescriptor fd = mFileDescriptor.getFileDescriptor();
        mInputStream = new FileInputStream(fd);
        mOutputStream = new FileOutputStream(fd);
        Thread thread = new Thread(null, this, "OpenAccessoryTest");
        thread.start();
        // Accessory opened
    } else {
        // failed to open accessory
    }
}
// close Accessory
private void closeAccessory() {
    try {
        // T.cancel();
        if (mFileDescriptor != null) {
            mFileDescriptor.close();
        }
    } catch (IOException e) {
    } finally {
        mFileDescriptor = null;
        mAccessory = null;
    }
}

Solution

  • According to the Android USB host documentation, your application has permission to access the device until the device is disconnected. This question provides a solution to suppress the permission dialog. Create an intent filter in your manifest file and provide the device information in an xml file. This would enable enumerating the device using a broadcast receiver.

    Another reference is this question. The latter is meant for rooted devices and I haven't tried it personally.

    Edit:

    Manifest File: I register my Broadcast Receiver in the manifest file.

    <receiver android:name="MyReceiver">
                     <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" />
    </receiver> 
    

    For the sake of convenience, I have my Broadcast Receiver in a separate class:

    public class PmrtReceiver extends BroadcastReceiver {
    
    
    public void onReceive(Context context, Intent intent) {
    
            String action = intent.getAction();
            if(UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)){
    
                Toast.makeText(context, "Device Detected",Toast.LENGTH_LONG).show();
    
    
            } else if(UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)){
    
                Toast.makeText(context, "Device Detached",Toast.LENGTH_LONG).show();
    
            }
    
        }
    
    };
    

    I did not have to do anything else to suppress the permission dialog.

    Look into the USB Missile Launcher example from the Android Samples. Your device filtr should be something like this:

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

    You have the VID and PID as hexadecimal numbers.