Frage

I am implementing an AlarmManager to request an update for my app which should happen only once per day. I don't want the alarm to go off as soon the alarm is created. For this I have created a calendar object.

It also fires whenever the alarm is created. Note that this doesn't always happen. I have noted that this problem occurs only on certain time of the day. I live in Hong Kong and I hope there's not any problem related due to my time zone. Instead of using AlarmManager.INTERVAL_DAY I have also tried using 24*60*60*1000. This happens only if the calendar mills is older than the current mills. I will checking if the time current time is newer and add 24*60*60*1000 in the calendar object, before deleting this question.

Here is a service that creates an AlarmManager. This service also starts on boot. Just to make sure about the dataPreferenceObj, it is an instance of DataPreference class in my application which handles SharedPreferences related calls for my application. And ACTION_SCHEDULE_ALARM is a part of Keys ENUM class which holds all the string constant.

public class TukiService extends Service {

private static AlarmManager calendarAlarmManager;
private static PendingIntent calendarPendingIntent;
private static final int SCHEDULE_REQUEST_CODE = 1001;

@Override
public void onCreate() {
    super.onCreate();

    updateScheduleUpdate();
}

private static void updateScheduleUpdate() {

    if (dataPreferenceObj.getEnabledUpdate() == true) {
        cancelScheduleUpdate();
        requestScheduleUpdate();
    } else if (dataPreferenceObj.getEnabledUpdate() == false) {
        cancelScheduleUpdate();
    }
}

private static void requestScheduleUpdate() {
    setScheduleAlarmParamaters();

    Calendar calendar = new GregorianCalendar();
    calendar.set(Calendar.HOUR_OF_DAY, 9);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    scheduleAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
            calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,
            schedulePendingIntent);
}

/*
 * Cancels an existing alarm if user doesn't want to auto update.
 */
private static void cancelScheduleUpdate() {
    setScheduleAlarmParamaters();
    scheduleAlarmManager.cancel(schedulePendingIntent);
}

private static void setScheduleAlarmParamaters() {
    Intent intent = new Intent(Keys.ACTION_SCHEDULE_ALARM.toString(),
            Uri.parse(Long.toString(SCHEDULE_REQUEST_CODE)), context,
            AlarmReceiver.class);

    schedulePendingIntent = PendingIntent.getBroadcast(mContext,
            SCHEDULE_REQUEST_CODE, intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    scheduleAlarmManager = (AlarmManager) mContext
            .getSystemService(Context.ALARM_SERVICE);
}

}

Here is an broadcast receiver that receives a broadcast:

public class ScheduleReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

    if (intent.getAction().equals(Keys.ACTION_SCHEDULE_ALARM.toString())) {

        if (TukiService.SCHEDULE_REQUEST_CODE == Long.parseLong(intent
                .getData().getSchemeSpecificPart())) {
            new NetworkHandler(context).fetchAutoEnabledUpdate();
        }
    } 
}

}

Here is my receiver declaration in the mainfest:

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <receiver
        android:name="com.milanix.tuki.service.ScheduleReceiver"
        android:enabled="true" >
    </receiver>
    <service android:name="com.milanix.tuki.service.TukiService" >
    </service>
War es hilfreich?

Lösung

I have solved this problem now. It seems like if triggerAtMillis is older than the currentMillis, the alarm will be fired no matter when you set it. I have written a following code which checks if triggerAtMillis is older than the currentMillis. If it is older than we will add a day interval in triggerAtMillis. Now no matter when i set an alarm it will always fire at the exact time and if the alarm time is in past it will fire next day at same time. Here's the code for that :

public static final int INTERVAL_DAY = 24 * 60 * 60 * 1000;

private static void requestScheduleUpdate() {
    setScheduleAlarmParamaters();

    Calendar calendar = new GregorianCalendar();
    calendar.set(Calendar.HOUR_OF_DAY, 15);
    calendar.set(Calendar.MINUTE, 55);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    long triggerMillis = calendar.getTimeInMillis();

    if (calendar.getTimeInMillis() < Calendar.getInstance()
            .getTimeInMillis()) {
        triggerMillis = calendar.getTimeInMillis() + INTERVAL_DAY;

        System.out.println("Alarm will go off next day");
    }

    scheduleAlarmManager
            .setRepeating(AlarmManager.RTC_WAKEUP, triggerMillis,
                    AlarmManager.INTERVAL_DAY, schedulePendingIntent);
}

It will be great if anyone can point out better solution than this one.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top