Implementing a WakefulIntentService in a multiple

2019-09-04 04:12发布

问题:

I have a application which needs to poll data at frequent intervals. I had an App Service logic with TimerTask implementation but then I moved to WakefulIntentService by @Commonsware.

Now my problem is that I have multiple activity screens that respond to a broadcast intent sent out by the Service. How do I ensure that the call to scheduleAlarms will be called only once (or is it not necessary that I bother about this?). The actual problem is that the code to scheduleAlarms is placed on a onCreate of a super class from which most if not all of the activities extend, thus resulting in multiple alarms scheduled.

回答1:

I have a application which needs to poll data at frequent intervals. I had an App Service logic with TimerTask implementation but then I moved to WakefulIntentService by @Commonsware.

WakefulIntentService is designed for what I would consider to be infrequent intervals (max of every few minutes), running decoupled from any UI. It sounds like that is not how you are using it.

How do I ensure that the call to scheduleAlarms will be called only once

Keep track of when you call it.

or is it not necessary that I bother about this?

That depends a bit on the schedule.

For alarms where you are aiming for particular times (say, 4pm next Tuesday), you can blindly reschedule them, because 4pm next Tuesday is not changing. If you are using an equivalent PendingIntent each time, Android will cancel the old alarm in the process of replacing it with the new one.

For periodic alarms (every N minutes/hours/days), you can just blindly reschedule them, with one caveat: your schedule will shift slightly unless you take care to avoid it. Let's say that you want an alarm to go off once per day. 12 hours after the last alarm, you reschedule the alarm to go off once per day again. If you want to make sure that the alarm still goes off in another 12 hours (to stick to your original schedule), you will need to know that this is required and to set the initial event in your setRepeating() call to the right time.



回答2:

I'm not sure what you want to do, but this is what I did:

In a certain activity:

Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 30);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);

AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30000, pendingIntent);

This sets up an alarm which triggers the AlarmReceiver class every 30 seconds.

In AlarmReceiver I have this:

package com.android.example;

import com.commonsware.cwac.wakeful.WakefulIntentService;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Intent i = new Intent(context, AlarmService.class);
        WakefulIntentService.sendWakefulWork(context, i);

    }
}

And in AlarmService I have this:

package com.android.example;

import android.content.Intent;
import com.commonsware.cwac.wakeful.WakefulIntentService;

public class AlarmService extends WakefulIntentService {

    public AlarmService() {
        super("AlarmService");
    }

    @Override
    protected void doWakefulWork(Intent arg0) {

        //DO WAKEFUL STUFF

    }
}

And I'll tell you what: It works!

I hope this helps!