Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to run a never ending service in Android

I have a service that gives a notification if user has changed his location. I want this service to keep on running until user explicitly force stops my application in application manager. I have used following method:

        Intent intent1 = new Intent(context, LocationService2.class);
        PendingIntent contentIntent = PendingIntent.getService(context, 0, intent1, 0);
        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),2*60000, contentIntent);

Service class:

public class LocationService2 extends Service implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.v("TAG", "STARTLS");
    mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

    mGoogleApiClient.connect();
    return START_STICKY;
}

@Override
public void onConnected(Bundle bundle) {
    Log.i(TAG, "Location services connected.");

    Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    // Use this location to give notification if required.
}

@Override
public void onConnectionSuspended(int i) {
    Log.i(TAG, "Location services suspended. Please reconnect.");
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onDestroy() {
    super.onDestroy();
    mGoogleApiClient.disconnect();
}
}

This method does not work on all phones. Is AlarmManager the best way to do this. If yes, then how can I improve this code to work on all phones?

like image 517
Tushar Kathuria Avatar asked Dec 11 '15 04:12

Tushar Kathuria


2 Answers

You should make your service a Foreground Service. You can find a tutorial here.

like image 89
Eric B. Avatar answered Oct 21 '22 22:10

Eric B.


Manifest Entry

<receiver android:name="YourPackagename.RestartReceiver">
<intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

<receiver android:name="YourPackagename.AlarmReceiver" >
</receiver>

On phone reboot need to reinitialize alarm manager RestartReceiver.java

public class RestartReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intentReciever = new Intent(context, AlarmReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intentReciever, 0);
            alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, (System.currentTimeMillis() + GlobalContext.PUSH_NOTIFICATION_INTERVAL),
                    GlobalContext.PUSH_NOTIFICATION_INTERVAL, alarmIntent);
        }
    }

}

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        //you can put your logic over here
    }
}

Put below code in your Splash Screen

private void initService() {
        if(!app_preferences.getBoolean("isServiceRunning", false))
        {
            AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            Intent intentReciever = new Intent(LoadingScreen.this, AlarmReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(LoadingScreen.this, 0, intentReciever, 0);
            alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, (System.currentTimeMillis()+GlobalContext.PUSH_NOTIFICATION_INTERVAL),
                    GlobalContext.PUSH_NOTIFICATION_INTERVAL, alarmIntent);
            app_preferences.edit().putBoolean("isServiceRunning", true).commit();
        }
    }

//Note: its not good way to check your Alerm service using shared preference is running or not.

like image 30
Bhavesh Jethani Avatar answered Oct 21 '22 22:10

Bhavesh Jethani