Is there a way to stop USB devices from triggering Android activity's pause/resume cycle?

198 views Asked by At

The following is in AndroidManifest.xml for MainActivity:

   <activity
        android:name=".MainActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:directBootAware="true"
        android:exported="true"
        android:icon="@mipmap/ic_launcher_round"
        android:launchMode="singleInstance"
        >
        <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>

If I plug in USB devices A, B, and C for the first time, the OS prompts me to select the app. This is exactly what it should be. After I unplug all of them, then plug them back, MainActivity pauses and resumes three times (i.e., pauses and resumes, and in a fraction of a second, pauses and resumes again, then in a faction of a second, pauses and resumes for the last time). The app is always in the foreground.

This is not a huge problem. It is manageable. I am curious if there is a way to avoid this kind of useless pause/resume cycle when the app is already in the foreground.

2

There are 2 answers

2
Jesse Sealand On

Potential Solution:

With no way to test, here is one possible reason this could be happening.

You are running with launchMode as 'singleInstance'. It is possible that the three pause-resume cycles you experience when plugging the three usb devices back are three restart cycles.

Try setting

android:launchMode="singleTop"

Documentation singleTop

If an instance of the activity already exists at the top of the target task, the system routes the intent to that instance through a call to its onNewIntent() method, rather than creating a new instance of the activity.

My reasoning is that singleTop might specifically route the newIntent to the already running instance. It's one possible solution, given the information we have available.

2
danielRICADO On

Don't think you can stop it. but you can use a broadcast receiver to detect the attached / detached event and take action from there.

(disclaimer untested)

private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
            // USB device attached, handle it
        } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
            // USB device detached, handle it
        }
    }
};

https://developer.android.com/reference/android/hardware/usb/UsbManager