There is a clock widget in our app.
The widget needs to be updated every minute to display the time right.
In Android O, it is advised to use JobScheduler for background updates.
Unfortunately, there are limitations.
- The periodic updates of JobService can not be called in less than 15 minutes intervals.
- The moment JobService.onStartJob() is unpredictable. We may miss the exact moment to update the minute digit (59th second).
Prior O we used to run a background service with Handler.postDelayed() to update the time in the widget.
In O the background service can be terminated by the system.
How would you recommend to implement a clock widget in Android O?
Is this even possible now?
Use "TextClock" widget control, it is supported by RemoteView functionality and it updates every minute by it self, no need to use those fancy JobScheduler jobs.
Something like this will do the trick:
<LinearLayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextClock
android:id="@+id/dateText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:format12Hour="@string/date_text_format_12h"
android:format24Hour="@string/date_text_format_24h"
android:gravity="bottom|center_horizontal"
android:textColor="@android:color/black"
android:textSize="@dimen/date_text_size_default"/>
<TextClock
android:id="@+id/timeText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:format12Hour="@string/time_text_format_12h"
android:format24Hour="@string/time_text_format_24h"
android:gravity="top|center_horizontal"
android:textColor="@android:color/black"
android:textSize="@dimen/time_text_size_default"
android:textStyle="bold"/>
</LinearLayout>
It's a widget; it doesn't need to update all the time -- only when it's visible. Why would you want to waste battery keeping track of the current time while your widget isn't running?
When the widget becomes visible, look up the current time and draw that right away. Also, calculate when the top of the next minute is, and post a delayed message or Runnable to a handler that will trigger at that moment. When that message/Runnable executes, update your time display and re-post the message/Runnable for the top of the next minute.
You should also register a receiver for the Intent.ACTION_TIME_CHANGED
broadcast that the Alarm Manager sends out when the current time is changed; you need to recalculate your displayed time and when the next update will happen in response to that broadcast.