6

The application that I am working on connects successfully with a device over the USB connection.

Additionally, it now remembers the device from different launches as also pointed out in the following thread storing usb default connections.

However, this leaves the undesired effect of always launching the Activity when the USB device is attached. I have not been able to remember the defaults without launching the application. Launching the application on a connect is not a desired effect. Small code samples below are what the manifest currently looks like in order to get the default USB connections stored in memory for future connections at a quick glance. Can this storage of defaults be done without causing an application launch?

<activity
     android:name="com.MainScreen"
     android:theme="@style/Theme.Default"
     android:configChanges="orientation|keyboardHidden|screenSize"
     android:label="@string/app_name">  
     <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>

I had been thinking that perhaps there was a type of category that I could add to the intent filter that would specify it as a non-launchable intent. Something that was listened for during the activity, but handled by the activity. So far, I haven't found this however.

Update:

Declaring the intent for usb device connection within a service or a receiver in the manifest has also been an attempt at storing connection information. However, only the intent within an activity remembers connection state so that it doesn't need to ask the user a subsequent time when it is re-connected at a later given point in time. It looks as though it is designed only to save state combined with launching an application when it is connected. A bit odd, but no workaround for getting a no-launch combined with remembering the default connection for usb attached device.

Community
  • 1
  • 1
Jay Snayder
  • 4,298
  • 4
  • 27
  • 53

3 Answers3

3

You don't have to launch an activity always. You can let a background service handle the intent quietly.

<service android:name=".MyService">
     <intent-filter>
          <action  android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
     </intent-filter>
</service>

Update:

You might have to request some permissions explicitly. Here's what you should do:

  1. When user installs the app and open it first time, ask for USB related permissions.
  2. Set a service to handle USB attach event as mentioned above. When attached, display a persistent notification in status bar as long as a recognized device is attached.
  3. The status bar notification is also useful to notify user that more permissions are required and main UI activity can be accessed.
S.D.
  • 29,290
  • 3
  • 79
  • 130
  • 1
    The device will not be remembered from within a service. So putting the filter there might not launch the device upon connection, but it will also not remember the device when it is connected and then disconnected. It's remembering and not-launching combined that I can't seem to get as a result. – Jay Snayder Aug 05 '13 at 13:45
  • @JaySnayder `The device will not be remembered from within a service` . . . why ? – S.D. Aug 05 '13 at 14:23
  • That has been what has been discovered through research of other articles. A couple articles had mentioned creating small wrapper Activities for the service in order to remember the default answer for when a device connects a subsequent time. I decided to try it anyway, but it won't remember the users decision in a service. – Jay Snayder Aug 05 '13 at 14:34
  • @JaySnayder That's strange. But still you can create a `BroadcastReceiver` class, register it in manifest for usb intents, inside `onReceive()` of receiver, extract all data you need from usb intent. Then start the service with extracted data. – S.D. Aug 05 '13 at 14:44
2

You should make a small re-design.

Create a Service and run the logic like 'When USB device attached' etc. (probably you have them in that Activity now) within this service.

By the way, you can always make good use of your MainActivity from or apart from this service.

faradaj
  • 3,629
  • 1
  • 22
  • 21
  • Handling the usb communications in a service is probably the proper route rather than handling it within my activity and using AsyncTasks for certain tasks. However, I don't quite follow the use of a service in both storing defaults. Putting an intent there within a service doesn't seem to store user selected defaults in remembering the device. – Jay Snayder Aug 05 '13 at 13:49
1

I can confirm by my own experiments that the USB device will not be remembered from within a service. It seems that requestPermission() must come out of an Activity.

To avoid the launch of the activity, I implemented onPostCreate() like this:

@Override // from Activity
public void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);

    Intent triggerIntent = getIntent();
    if (triggerIntent != null) {
        if ( ! triggerIntent.hasCategory(Intent.CATEGORY_LAUNCHER) ) {
            Log.e(LOGTAG, "not started by launcher! exit now.");
            finish();
        }
    }
}

I used onPostCreate() instead of pasting the code into onCreate() because when calling finish() from onCreate() it will cause onDestroy() to be called immediately and typically not all members of the Activity class are setup properly yet. It seems to be more safe to me using the onPostCreate() approach.

zoulou
  • 121
  • 4