I have a service which sends a notification when the user changes his/her location. This service is working fine, but the problem arises when the user closes the app as the
Oppositely to what @sven-menschner said, I think an unbound Service
is exactly what you need, as bound services are subject to bind/unbind mechanisms that would kill your service. That's what I would do:
In your Manifest file, define your service:
<service
android:name=".YourService"
android:enabled="true"
android:exported="true"
android:description="@string/my_service_desc"
android:label="@string/my_infinite_service">
<intent-filter>
<action android:name="com.yourproject.name.LONGRUNSERVICE" />
</intent-filter>
</service>
Note: There's a list of already implemented actions, but you can define your own actions for the intent to launch the service. Simply create a singleton class and define the strings assigning them a String
that should be unique. The "enabled" set to true is just to instantiate the service, and exported set to true is just in the case you need other applications sending intents to your Service
. If not, you can safely set that last to false.
The following step would be starting your service from your activity. That can be easily done by:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent servIntent = new Intent("com.yourproject.name.LONGRUNSERVICE");
startService(servIntent);
...
}
}
The final step is to define your Service
initializations. Keep an eye on the onBind()
method. Since you don't want it to be bound, simply return null
. It would be something like this:
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
// This won't be a bound service, so simply return null
return null;
}
@Override
public void onCreate() {
// This will be called when your Service is created for the first time
// Just do any operations you need in this method.
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
Now your service will run even if you close your main Activity
. There's just one step left: To help your Service
not being finished, run it as a foreground service (do that within your Service). This will basically create a notification icon in the status bar. This doesn't mean your main Activity is running too (this is why you don't want a bound service), as Activities and Services have different life-cycles. In order to help that Service run for so long, try keeping your heap as low as possible so it will avoid the Android SO killing it.
One more acclaration: You cannot test whether the Service is still running killing the DVM. If you kill the DVM, you'll killing everything, thus also the Service.
There are two kinds of Android Services: started and bound. You need to use the first one(started Service). The documentation shows how to use it, there is a nice lifecycle diagram below.
Instead of starting and binding the service in one step using bindService()
you need to call startService()
first. However startService()
won't help you starting from Oreo. You need to usestartForegroundService()
from there. Then it runs until you stop it, even if the app is closed.
Start Sticky Service
if you want Android OS
to pick your service again if it killed it.