Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop a service at a specific time of the day?

I have been able to start a service at specific time of every day but I want to do the exact same thing to stop but I don't know how.


Here is the code I use to start the service using AlarmManager.
note: I am new to android dev so providing a full commented code will be highly appreciated.

 Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 9);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    PendingIntent pi = PendingIntent.getService(getApplicationContext(), 0,
            new Intent(getApplicationContext(), Service.class), PendingIntent.FLAG_NO_CREATE);
    AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, pi);
like image 441
Hamed Baatour Avatar asked Mar 13 '16 17:03

Hamed Baatour


People also ask

How do I stop a service from another activity?

You can add a shutdown() method into your AIDL interface, which allows an Activity to request a stopSelf() be called. This encapsulates the stopping logic and gives you the opportunity to control the state of your Service when it is stopped, similar to how you would handle a Thread .

Is the method used to stop service?

Service can stop itself by calling methods as follows. stopSelf(): On calling it, Service is stopped if it is running. stopSelfResult(int startId): Stops the service for the most recent start id.

Can we stop the services in Android?

Fundamentals of Android ServicesOnce the service is started, it can be stopped explicitly using stopService() or stopSelf() methods.


2 Answers

Service can be stopped from any running class provided you should have the context. From the following steps you can stop the running service at specific time using Receiver.

1. Create a WakefulBroadcastReceiver class in your application. On receive action check if service is running or not,if running stop using Context.

public class TestReceiver extends WakefulBroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    if(intent.getAction().equalsIgnoreCase("STOP_TEST_SERVICE")) {
        if (isMyServiceRunning(context, TestService.class)) {
             Toast.makeText(context,"Service is running!! Stopping...",Toast.LENGTH_LONG).show();
             context.stopService(new Intent(context, TestService.class));
        }
        else {
            Toast.makeText(context,"Service not running",Toast.LENGTH_LONG).show();
        }
    }

}
private boolean isMyServiceRunning(Context context,Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

}

2. Register the receiver in AndroidManifest.

<receiver android:name=".TestReceiver">
        <intent-filter>
            <action android:name="STOP_TEST_SERVICE" />
            <action android:name="START_TEST_SERVICE" />

        </intent-filter>
    </receiver>

3.Create a PendingIntent with desired action, then set scheduled action using AlarmManager in your activity class.

 public void setStopServiceAlarm() {
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 15);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 0);

    AlarmManager alarm = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);

    PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0,
            new Intent().setAction("STOP_TEST_SERVICE"), PendingIntent.FLAG_UPDATE_CURRENT);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        alarm.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
    } else {
        alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
    }
}

Hope this helps!!

like image 119
Bharath Kumar Avatar answered Oct 22 '22 18:10

Bharath Kumar


In the same way.

When you launch a Service with an Intent (or through a PendingIntent) Android start the service if needed, will call onCreate() if that's the case, then the onStartCommand(intent, flags, startId) method passing the Intent and a startId.

The Service is supposed to manage its own lifecycle and call stopSelf() when it's done, when the service is destroyed by Android the onDestroy() method is called.

The only other way of starting a Service is binding to it from an Activity. This does not trigger a call to onStartCommand(), it calls onBind() instead.

Android terminate the service if

  • the service call stopSelf() and there is no Activity binded to it
  • the service is unbinded from an Activity, there are no other bind nor other commands for which the stopSelf() has not been called
  • low resources on the device (this is where the START_STICKY flags and those kind of flags comes into play)

The stopSelf() method has a stopSelf(int) version. Calling it without parameters means: I'm done with all, stop me; calling it with the integer means: I'm done if no other command has been received after this one; the integer is one of the startId you get in onStartCommand() method. If you have a queue of operation running one after the other it is natural to call stopSelf(int) after each operation has run, otherwise your Service need to know when to call stop.

So usually a Service should "know" what it is doing and stop itself when its done but you can launch an Intent with a specific action (say "ACTION_STOP") for that Service and handle that action calling stopSelf(). If it was running this will stop it (your responsibility to close any background thread / release any resource, maybe in onDestroy()). If it wasn't running it will start and immediately stop.

That said I invite you to think about what you are doing. You didn't specified but your request is a bit weird, I can't think of a reason why a service shutdown should be scheduled.

Finally, consider having a look at JobScheduler for Lollipop and later. It's better for battery usage.

like image 24
Daniele Segato Avatar answered Oct 22 '22 20:10

Daniele Segato