Keep your location service alive when the application is closed.

I have a service that sends a notification when a user changes his location. This service works fine, but the problem occurs when the user closes the application, when the service closes too.

How can I make the service still alive, even if the application was closed?

My service:

public class LocationService extends Service implements LocationListener { public final static int MINUTE = 1000 * 60; boolean isGPSEnabled = false; boolean isNetworkEnabled = false; boolean canGetLocation = false; Location location; // location double latitude = 0; // latitude double longitude = 0; // longitude String provider; // The minimum distance to change Updates in meters private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // The minimum time between updates in milliseconds private static final long MIN_TIME_BW_UPDATES = 1 * MINUTE; // Declaring a Location Manager protected LocationManager locationManager; // Binder given to clients private final IBinder mBinder = new LocalBinder(); /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { public LocationService getService() { // Return this instance of LocalService so clients can call public // methods return LocationService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } public Location getLocation() { try { locationManager = (LocationManager) getBaseContext().getSystemService(LOCATION_SERVICE); // getting GPS status isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); // getting network status isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (!isGPSEnabled && !isNetworkEnabled) { // no network provider is enabled. DEFAULT COORDINATES } else { this.canGetLocation = true; if (isNetworkEnabled) { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("Network", "Network Enabled"); if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } // if GPS Enabled get lat/long using GPS Services if (isGPSEnabled) { if (location == null) { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("GPS", "GPS Enabled"); if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } } } } catch (Exception e) { e.printStackTrace(); } Log.i("LOCATION", "Latitude: " + latitude + "- Longitude: " + longitude); return location; } @Override public void onLocationChanged(Location arg0) { NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); Intent intent = null; intent = new Intent(this, CompleteSurveyActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_launcher).setAutoCancel(true) .setContentIntent(contentIntent).setContentTitle(this.getString(R.string.app_name)).setContentText("text"); // mBuilder.setContentIntent(contentIntent); mNotificationManager.notify((int) System.currentTimeMillis() % Integer.MAX_VALUE, mBuilder.build()); double longitude = location.getLongitude(); double latitude = location.getLatitude(); Log.i("LOCATION", "Latitude: " + latitude + "- Longitude: " + longitude); } @Override public void onProviderDisabled(String arg0) { } @Override public void onProviderEnabled(String arg0) { } @Override public void onStatusChanged(String arg0, int arg1, Bundle arg2) { } } 

I called from here:

 public class MyActivity extends Activity { LocationService mService; boolean mBound = false; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get // LocalService instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); exampleButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { initService(); } }); } public void initService() { if (mBound) mService.getLocation(); } @Override protected void onStart() { super.onStart(); // Bind to LocalService Intent intent = new Intent(this, LocationService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } } 

Manifest.xml

  <service android:name=".LocationService" android:enabled="true"></service> 
+6
source share
2 answers

Against what @ sven-menschner said, I think the unbound Service is exactly what you need, as related services are subject to the bind / unbind mechanisms that will kill your service. What would I 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 Here is a list of actions already implemented, but you can define your own actions for the intention to start the service. Just create a singleton class and define the strings by assigning them a String , which must be unique. β€œEnabled” set to true is just an instance of the service, and the exported set is true only if you need other applications that send intentions to your Service . If not, you can safely set the latter to false.

The next step is to start the service from your activity. This is easy to do:

 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. Watch out for the onBind() method. Since you do not want this to be related, just return null . It will 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 be launched, even if you close your main Activity . There is only one step left: to prevent your Service from ending, start it as a front-end service (do it in your service). This will basically create a notification icon in the status bar. This does not mean that your main activity also works (therefore, you do not need a related service), since Activities and Services have different life cycles. To help this service work for so long, try to keep your heap as low as possible so that it avoids Android SO killing it.

Another invitation: you cannot check if the Service continues to kill DVM. If you kill DVM, you will kill everything, and thereby the Service.

+8
source

There are two types of Android services: started and tied. You are looking for the latter. The documentation shows how to use it, the following life cycle diagram.

Instead of starting and binding the service in one step using bindService() you need to call startService() . Then it starts until you stop it, even if the application is closed. But remember to stop the service at the right time to avoid memory problems, etc.

NTN

+2
source

All Articles