6

I want to write a service in Android which starts based on USB_DEVICE_ATTACHED intent. So, basically my service should start when a specific USB Device(FT232C - VID:PID 0403:6010) is connected and stop when that USB device is detached. Is it possible to do that or should I always have an Activity which starts this service in case it is not already started? The intent of the service in the end is to update the location on the LocationProvider with a TEST_PROVIDER based on what location is provided from this USB device.

I already tried creating a service with this configuration in AndroidManifest.xml

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.testlocservice"
        android:versionCode="1"
        android:versionName="1.0">

        <uses-sdk android:minSdkVersion="12" android:targetSdkVersion="15" />
        <uses-feature android:name="android.hardware.usb.host"/>
        <supports-screens android:resizeable="true" android:smallScreens="true" android:anyDensity="true" android:largeScreens="true" android:xlargeScreens="true" android:normalScreens="true"/>
        <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        <uses-permission android:name="android.permission.READ_PHONE_STATE"/>

        <application android:label="@string/app_name"
            android:icon="@drawable/ic_launcher"
            android:theme="@style/AppTheme">
                <service android:name="com.testlocservice.LocationService"         android:process=":LocService" android:enabled="true" android:exported="true">
                    <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" />                
                </service>
        </application>
    </manifest>

The xml/device_filter.xml contains this

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

My LocationService class has overridden onStartCommand() which handles the USB_DEVICE_ATTACHED intent

user1400473
  • 61
  • 1
  • 3

3 Answers3

8

From my experience a <service> cannot receive the USB intents. I overcame this by creating a hidden activity to receive the intent and re-broadcast it. Of course this activity could also handle starting/stopping your service.

I have already put up some working code here:
https://stackoverflow.com/a/15151075/588476
You will just have to change it so it starts and stops your service automatically.

Community
  • 1
  • 1
Wayne Uroda
  • 5,025
  • 4
  • 30
  • 35
  • 1
    Android has three ways to send an Intent: `sendBroadcast()`, `startActivity()` and `startService()`. Apparently each of these ways delivers the Intent only to the intended component type. `USB_DEVICE_ATTACHED` appears to be sent via `startActivity()`, hence an Activity can receive it, but a Service or BroadcastReceiver cannot (I tried both). Conversely, the `USB_DEVICE_DETACHED` event is sent as a broadcast, hence it takes a `BroadcastReceiver` to pick it up. – user149408 May 29 '17 at 20:35
1

I believe the main problem is the number base for the vendor and product id's. The format in the device filter xml should be decimal, so vendor-id="1025" and product-id="24592".

Aside from that, it absolutely should be USB_DEVICE_ATTACHED, rather than UMS_CONNECTED (the latter is not USB host mode at all).

I don't have the authoritative answer as to whether a service could receive a broadcast intent, or whether you have to use an activity for that, but it seems like Wayne Uroda has good experience with this question.

Raph Levien
  • 5,088
  • 25
  • 24
0

Yes, it is very well possible, sorry to say that you are using wrong intent-filter in your reveiver tag in AndroidManifest.xml. Let me guide you

AndroidManifest.xml

.
.
.
<receiver android:name=".DetactUSB">
   <intent-filter>
        <action android:name="android.intent.action.UMS_CONNECTED" />
        <action android:name="android.intent.action.UMS_DISCONNECTED" />
   </intent-filter>
</receiver>

BroadcastReceiver file

public class DetactUSB extends BroadcastReceiver
{ 
    private static final String TAG = "DetactUSB";
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        // TODO Auto-generated method stub
        if (intent.getAction().equalsIgnoreCase( "android.intent.action.UMS_CONNECTED"))
        {
                // Fire your Intent to start Activity
                Log.i(TAG,"USB connected..");
        }
        if (intent.getAction().equalsIgnoreCase( "android.intent.action.UMS_DISCONNECTED"))
        {
        }
    } 
}
Lucifer
  • 29,392
  • 25
  • 90
  • 143
  • This detects any USB but i should probably try using my intent-filter which detects the USB_DEVICE_ATTACHED based on the VID:PID in a BroadcastReceiver and then fire my service from there. Will try that and see – user1400473 Nov 20 '12 at 03:51
  • The BroadcastReceiver is not receiving the intents. Do i need to register it separately in the onCreate() of the service. – user1400473 Nov 20 '12 at 17:56
  • @user1400473, no Registration is already done in AndroidManifest.xml – Lucifer Nov 21 '12 at 02:02
  • 1
    UMS_CONNECTED appears to be related to the Android device connecting to a computer as a mass storage device, and was deprecated in API 14: http://developer.android.com/reference/android/content/Intent.html#ACTION_UMS_CONNECTED – Wayne Uroda Mar 10 '13 at 23:37