How to update an app widget on midnight?
Asked Answered
P

2

7

My app has a widget that shows today's date and need to be updated on midnight. The widget is defined in the manifest as

<manifest>
    ...
    <application>
        ...
        <receiver
            android:name=".MyWidgetProviderClass"
            android:label="MyLabel" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_icon_info" />
        </receiver>
    </application>
</manifest>

And the widget info file is

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/my_layout"
    android:minHeight="40dp"
    android:minWidth="294dp"
    android:updatePeriodMillis="3600000" >
</appwidget-provider>

This causes the widget to get updated anytime between midnight and 1pm but I want to to get updated closer to midnight so I added to the app an intent receiver

<receiver
     android:name=".MyWidgetUpdaterClass"
     android:enabled="true" >
     <intent-filter>
         <action android:name="MyAction" />
      </intent-filter>
</receiver>

and a static method

public static void setMidngintAlarms(Context context) {
    Intent intent = new Intent("MyAction");
    PendingIntent pendingIntent = 
        PendingIntent.getBroadcast(context, 0, intent, 0);              
    long interval = 24*60*60*1000;        
    long firstTime = SystemClock.elapsedRealtime() + 
        millisecondsToNextMidnight();
    AlarmManager am = (AlarmManager)context.getSystemService(
        Context.ALARM_SERVICE);
    am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    firstTime, interval, pendingIntent);
}

(since alarm manager requests with the same intent overwriting each other there is not harm in calling setMidngintAlarms multiple times).

I tried calling setMidnightAlarms() from few places (from the app's main activity, from the AppWidgetProvider's onUpdate(), etc). Everything works well and the alarm manager intents are received and the widget is updated but only as long as the app runs. If I killed the app, the widgets stops updating on midnight.

Any idea how to cause the widgets to update on midnight? Do I need to add a service? If so how? Any example?

I am a little bit surprised how non trivial it is to get this basic functionality to work.

Portfolio answered 5/1, 2012 at 23:39 Comment(2)
The widget should still update because you are setting an alarm for it. So it doesnt matter whether the app is running or not. It does mater if the device restarts and you dont register your alarm from the beginning.Hellhound
When a repeating alarm is set and is never canceled explicitly. Under what conditions does the android system cancel it, if at all? I could not find relevant info. For example, is it tied to the activity or service that sent it or does it live forever independently?Portfolio
S
0

I resolve this problem by:

  1. Start a service to listen to Intent.ACTION_TIME_TICK message. Then send a broadcast to widget if Time TICKED. (At every minute).

  2. Receive the broadcast in widget and judge weather it is the midnight by:

Code:

   if (MyWidget.BROADCAST_TIME_TICK.equals(action)) {
        //If it's midnight, then update.
        int hour = Calendar.getInstance().get(Calendar.HOUR);
        int minute = Calendar.getInstance().get(Calendar.MINUTE);
        Utils.log(TAG, "time is : " + hour+":" + minute);
        if (!(hour == 0 && minute == 0)) {  //Only update at midnight's time tick.
            return;
        } else {
            //Do the midnight stuff.
        }
    }
Susquehanna answered 10/8, 2012 at 8:51 Comment(0)
L
0

ad this to your manifest widget receiver

 <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            <action android:name="android.intent.action.DATE_CHANGED" />...

the change in date will trigger your onReceive() to fire up with the "android.intent.action.DATE_CHANGED" action

Luedtke answered 10/8, 2017 at 10:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.