Question

I had my app setup where a (non-intent) Service would poll the location using a gps/network listener. It worked fine since I was in charge of when the service would end (i.e. calling stopSelf() when a new location was found or the timeout was reached). However, I recently read that an intentService may be more suitable for a long-running task as it is not run on the ui thread, but its own worker thread. The problem is, now it does not allow the service to run for any time (I am assuming this is because nothing is actively happening in the service, while the listeners wait for a location to be received, and so the service ends itself).

my onStartCommand() method when it was a non intent service looked like:

@Override
protected void onStartCommand(Intent intent) {
    grabLocation();
}

Since I have switched the service to an intent service, I took away this method (as per the documentation, it should not be overridden for intentSerivce), and now my onHandleIntent service looks like so:

@Override
protected void onHandleIntent(Intent intent) {
    grabLocation(); 
}

The service ends almost immediately. What can I do to postpone when the service is ended?

I call the service like any other using startService(Intent)

locationPollingIntent = new Intent(MainActivity.this, LocationService.class);
updateLocationButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startService(locationPollingIntent);
        }
    });

Manifest snippet:

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <service
        android:name="com.rperryng.intellilocation.backgroundServices.LocationService"
        android:label="Location Service" />

    <receiver android:name="com.rperryng.intellilocation.backgroundServices.AutoStart" />

    <activity
        android:name="com.rperryng.intellilocation.activities.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
Was it helpful?

Solution

However, I recently read that an intentService may be more suitable for a long-running task as it is not run on the ui thread, but its own worker thread

Only for things that are "transactional" in nature: database I/O, Web service calls, downloading small files, etc. It is not suitable for cases like yours.

I am assuming this is because nothing is actively happening in the service, while the listeners wait for a location to be received, and so the service ends itself

More specifically, once onHandleIntent() returns, if there are no more commands waiting to be processed, the service calls stopSelf().

What can I do to postpone when the service is ended?

Go back to your original approach, but have the locations delivered to you on a background thread, by using a HandlerThread and the flavors of requestLocationUpdates() that take a Looper. That way, when your location arrives, you are on a background thread and can do whatever you need to do with the location, then you can stopSelf() to go away.

However, this gets tricky, insofar as you also need a timeout, in case you never get a location fix. And, you have to worry about keeping the device awake, so it does not fall asleep while you are waiting for a fix. I wrote a LocationPoller library that handles this stuff, though I have not used it in years, and so there is a fairly thick layer of dust on it.

You might consider using the PendingIntent flavors of requestLocationUpdates(), or its equivalent on the LocationClient API, as an alternative to any of this. Then, you can use an IntentService just for processing the results of a location fix.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top