Reputation: 249
I would like execute an action, wait n seconds, execute another action, wait again, etc (asynchronously).
Firstly, I got it using AsyncTask. The problem is that I need it occurs even when the device is locked (because the goal is to send orders to another device).
Then I've thought to use AlarmManager, doing something like that:
public class MainClass {
private static MainClass instance;
private static Context context;
private MainClass(){}
public static MainClass getInstance(Context context){
MainClass.context = context;
if (instance == null) instance = new MainClass();
return instance;
}
// [...]
private Alarm alarm = null;
private static Worker worker = null ;
private static Handler my_handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message message) {
worker.executeNextAction();
}
};
public void start(){
alarm = new Alarm();
worker = new Worker();
worker.executeNextAction();
}
public static class Alarm extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
my_handler.sendMessage(new Message());
}
public void setAlarm(Context context, int seconds)
{
AlarmManager alarm_manager =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, Alarm.class);
PendingIntent pending_intent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarm_manager.set(AlarmManager.RTC_WAKEUP, 1000 * seconds, pending_intent);
}
public void cancelAlarm(Context context) { /*[...]*/ }
}
private class Worker {
void executeNextAction() {
// do tasks
alarm.setAlarm(context, duration);
}
// [...]
}
}
This does not work because worker would be null in handleMessage()
.
How I can call the method executeNextAction()
from onReceive()
method?
Upvotes: 0
Views: 197
Reputation: 567
You can use PeriodicWorkRequest in Work Manager to run sequence jobs. Work Manager run background job gracefully and handle many cases like not running if no internet connection, low battery, etc (It use Constraint)
Upvotes: 0
Reputation: 885
WorkManager
is highly configurable and will allow you to create a PeriodicWorkRequest
or a OneTimeWorkRequest
these are guaranteed to succeed. PeriodicWorkRequest
will fire when you schedule the work, as well as when you have specified in the timer. It will execute in the background even if the app is closed or backgrounded. If you didn't want your task to execute immediately you can use a PWR(PeriodicWorkRequest) with a FlexInterval. See the docs below for more info.
For example, I created two PeriodicWorkRequests that refresh services and keeps the user logged in always by renewing their token. When the user authenticates the PeriodicWorkRequest
is created. In my case, I didn't need it to fire right away as they have just received and cached this information so I utilized the FlexInterval. When the app is backgrounded or closed, the workers continue to refresh services every 12 hours and refresh the token every 6. It works like a charm.
Here is an example:
Build Work:
override fun beginWork() {
val periodicWorkRequest = PeriodicWorkRequest.Builder(
MyWorker::class.java,
REPEAT_INTERVAL, TimeUnit.MINUTES, // How often work should repeat
// Flex not required.
FLEX_INTERVAL, TimeUnit.MINUTES) // Limits execution into a time window
.setConstraints(
Constraints.Builder().setRequiredNetworkType(
NetworkType.CONNECTED).build())
.addTag(MY_WORKER_TAG)
.build()
WorkManager.getInstance().enqueueUniquePeriodicWork(
MY_UNIQUE_WORK,
ExistingPeriodicWorkPolicy.KEEP,
periodicLoginRequest)
Worker:
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
// DO WORK HERE
Result.success()
} else {
// HANDLE FAILURE HERE
Result.failure()
}
The above is a simple implementation, but it should give you the general idea.
Upvotes: 2