Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

USB Permissions without prompt

I have 2 activities within my app. Say FirstActivity and SecondActivity. FirstActivity is the MAIN and LAUNCHER activity. SecondActivity uses usb devices. I want the prompt for USB permission to appear only once within lifetime of the app.

If there was only one Activity, the following lines in manifest solved my purpose:

<activity android:name=".FirstActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <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/usb_device_filter" />
</activity>

This was doing the following:

  1. Launching FirstActivity whenever usb device (mentioned in xml) is connected is app is not already open.
  2. Prompt for usb device permission appears only once.

How do I modify this to achieve the following:

  1. If SecondActivity is already running and a new usb device is attached, I must be able to use the device without relaunching the app. So I have written a broadcast receiver for the same as follows:

    public class TriggerReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { 
            read connected usb devices and register serial port call listener back.
        }
    }    
    

But the problem is FirstActivity gets relaunched again when usb device is attached while SecondActivity is running. How do I avoid this ?

Will add more information if needed. Would be thankful for any help.

like image 318
jay Avatar asked Oct 21 '16 17:10

jay


People also ask

How do I allow USB permissions?

To do this, your application has to: Discover connected USB devices by using an intent filter to be notified when the user connects a USB device or by enumerating USB devices that are already connected. Ask the user for permission to connect to the USB device, if not already obtained.

How do I give an app permission to a USB?

When you connect USB the first time (with already installed app), system call permission dialog. Then another time at start app usb will get permission automatically.

How do I change the permissions of a USB drive?

USB Drive Access Permission. 1 Right-click the USB's drive on File Explorer and select Properties. 2 Click the Security tab. 3 Select an Owner/User and click Edit. 4 Check all the options on the Allowed column, select OK and then Apply.

How to get permission to access inaccessible hard drive or USB?

So, another choice is to gain permission for the inaccessible hard drive, USB, or file folders: Step 1. Right-click the inaccessible hard drive, USB, or file folder, and select Properties. Step 2. Go to Security, click Advanced and navigate to the Owner tab. Step 3. Click on "Edit", click your username under Group or username.

How do I know if a USB device has been granted permission?

When the USB device is plugged in, if it hasn't already been granted permission then the USB permission box will popup. If the user clicks OK without checking the remember box, then the box will popup again the next time the device is connected.

How to give permissions to a drive in Windows 10?

Follow these steps to give permissions to the drive. a) Right-click on the folder which you’re unable to access and select Properties. b) Click on ‘Security’ tab and under ‘Group or user names’ click on ‘Edit’. c) Click on ‘Add’ and type ‘everyone’. d) Click on ‘Check names’ and then click ‘OK’.


3 Answers

Try "remove" intent filter <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> from FirstActivity like in this question

Update

FirstActivity triggers on every USB_DEVICE_ATTACHED (even SecondActivity is running) because You set <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> filter for it in AndroidManifest.xml file. So You should disable this filter when SecondActivity running. You can do this by that way:

1) add (e.g. AliasFirstActivity) in AndroidManifest.xml to your FirstActivity and move <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> filter to alias description (You should remove <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />from FirstActivity description) like that:

        <activity-alias
            android:targetActivity=".FirstActivity"
            android:name=".AliasFirstActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

            <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" />
        </activity-alias>

2) add this code to onCreate() (or to onResume()) of SecondActivity

PackageManager pm = getApplicationContext().getPackageManager();
        ComponentName compName =
                new ComponentName(getPackageName(), getPackageName() + ".AliasFirstActivity");
        pm.setComponentEnabledSetting(
                compName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);

to suppress intent filter USB_DEVICE_ATTACHED for FirstActivity. You should have in SecondActivity something like that:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        triggerReceiver = new TriggerReceiver();

        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        registerReceiver(triggerReceiver, filter);

        PackageManager pm = getApplicationContext().getPackageManager();
        ComponentName compName =
                new ComponentName(getPackageName(), getPackageName() + ".AliasFirstActivity");
        pm.setComponentEnabledSetting(
                compName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }

That should solve Your issue. 3) if it is needed, You can restore <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> filter for FirstActivity in onDestroy() (or in onPause()) of SecondActivity by using this code:

    PackageManager pm = getApplicationContext().getPackageManager();
    ComponentName compName =
            new ComponentName(getPackageName(), getPackageName() + ".AliasFirstActivity");
    pm.setComponentEnabledSetting(
            compName,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);
like image 67
Andrii Omelchenko Avatar answered Sep 29 '22 03:09

Andrii Omelchenko


But the problem is FirstActivity gets relaunched again when usb device is attached while SecondActivity is running. How do I avoid this?

This is not hard to answer. In your AndroidManifest.xml you literally declare that your FirstActivity should be launched when the event android.hardware.usb.action.USB_DEVICE_ATTACHED occurs.

If you want to handle this event in SecondActivity only, then you have to declare it in the manifest accordingly, for example:

    <activity android:name=".FirstActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity android:name=".SecondActivity" android:launchMode="singleTask">
        <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" />
    </activity>

Now, whenever your USB device is plugged in, SecondActivity will be launched only. If SecondActivity is already running, then it won't be launched again (or multiple times) because of the attribute android:launchMode="singleTask" specified for SecondActivity. You can read more about the different launch modes here if you're interested.

Since you declared in your manifest that SecondActivity should be launched when a USB device is plugged in, the Android system will ask you the following question:

USB Dialog

After ticking the checkbox "Use by default for this USB device", it won't ask you again. Now, everytime you plug in the USB device, your SecondActivity will be launched and it will automatically receive the required USB permissions too.

Let me know if that answers your question.

like image 44
reflective_mind Avatar answered Sep 29 '22 02:09

reflective_mind


This answer might be helpful: USB device access pop-up suppression?

Code snippet:

 public class UsbEventReceiverActivity extends Activity
     {   
        public static final String ACTION_USB_DEVICE_ATTACHED = "com.example.ACTION_USB_DEVICE_ATTACHED";
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
        }

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

        Intent intent = getIntent();
        if (intent != null)
        {
            if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED))
            {
                Parcelable usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                // Create a new intent and put the usb device in as an extra
                Intent broadcastIntent = new Intent(ACTION_USB_DEVICE_ATTACHED);
                broadcastIntent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice);

                // Broadcast this event so we can receive it
                sendBroadcast(broadcastIntent);
            }
        }

        // Close the activity
        finish();
    }
}
like image 41
Jamil Hasnine Tamim Avatar answered Sep 29 '22 02:09

Jamil Hasnine Tamim