Context
which is used here to change the widget data. With auto update feature, your widget become lively and useful!Today, by this post, I would like to present an updating widget, which displaying current time in HH:mm format.
Creating a Service class
Service
). Override onStartCommand()
method like this:
UpdateService.java
As you can see at the code above, remember update data (current time) to a package info.devexchanges.updatewidget;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.widget.RemoteViews;
import java.util.Calendar;
public class UpdateService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String time = getCurrentDateTime();
RemoteViews view = new RemoteViews(getPackageName(), R.layout.widget_updating);
view.setTextViewText(R.id.txt_widget, time);
ComponentName theWidget = new ComponentName(this, UpdatingWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(theWidget, view);
return super.onStartCommand(intent, flags, startId);
}
private String getCurrentDateTime() {
Calendar c = Calendar.getInstance();
int minute = c.get(Calendar.MINUTE);
int hour = c.get(Calendar.HOUR_OF_DAY);
return hour + ":" + minute;
}
}
TextView
in your widget after get time here!
Widget XML files
The layout for this widget:
layout\widget_updating.xml
And define the <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/txt_widget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_margin="8dp"
android:background="#09C"
android:text="@string/appwidget_text"
android:textColor="#ffffff"
android:textSize="24sp"
android:textStyle="bold|italic"/>
</RelativeLayout>
AppWidgetProviderInfo
object in an XML like this:
xml\updating_widget_info.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_updating"
android:minHeight="80dp"
android:minWidth="80dp"
android:previewImage="@mipmap/ic_launcher"
android:resizeMode="vertical"
android:updatePeriodMillis="0">
</appwidget-provider>
AppWidgetProvider class
Service
does not start by itself. We need to start the service (in every minute for this example) in the AppWidgetProvider
.But why we do not just use
updatePeriodMillis
atribute? The official document say that:
In previous examples, we usedIf the device is asleep when it is time for an update (as defined byupdatePeriodMillis
), then the device will wake up in order to perform the update. If you don't update more than once per hour, this probably won't cause significant problems for the battery life. If, however, you need to update more frequently and/or you do not need to update while the device is asleep, then you can instead perform updates based on an alarm that will not wake the device. To do so, set an alarm with anIntent
that yourAppWidgetProvider
receives, using theAlarmManager
. Set the alarm type to eitherELAPSED_REALTIME
orRTC
, which will only deliver the alarm when the device is awake. Then setupdatePeriodMillis
to zero ("0").
getActivity()
and getBroadcast()
methods. This time we are going to use getService()
:
UpdatingWidget.java
The minimum interval time is 60000 milliseconds for package info.devexchanges.updatewidget;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
public class UpdatingWidget extends AppWidgetProvider {
private PendingIntent pendingIntent;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final Intent i = new Intent(context, UpdateService.class);
if (pendingIntent == null) {
pendingIntent = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
}
manager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), 60000, pendingIntent);
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
}
AlarmManager
. If you need to call your service less than 60 second with an alarm manager, please read this discussion on StackOverflow. But you should pay attention: this action drains the battery and makes users delete your app.
Running application
I cropped the video to not keep you wait 4 minutes.
Conclusions
- Widget guideline at Material Design technology
- Widget official document
- A good tutorial post on Vogella