Android (Home screen) widget - Part 4: Update widget via Service

    The fact that, most of widgets that you can see on your device are auto-update information, for example: weather widget, location widget,... Service is the 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

    We'll get current time in the device in this class (which a subclass of Service). Override onStartCommand() method like this:
UpdateService.java
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;
    }
}
    As you can see at the code above, remember update data (current time) to a TextView in your widget after get time here!

Widget XML files

    Like another widgets at previous parts, your must create widget layout and property files (in XML).
    The layout for this widget:
layout\widget_updating.xml
<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>
    And define the 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:
If the device is asleep when it is time for an update (as defined by updatePeriodMillis), 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 an Intent that your AppWidgetProvider receives, using the AlarmManager. Set the alarm type to either ELAPSED_REALTIME or RTC, which will only deliver the alarm when the device is awake. Then set updatePeriodMillis to zero ("0").
    In previous examples, we used getActivity() and getBroadcast() methods. This time we are going to use getService():
UpdatingWidget.java
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);
    }
}
    The minimum interval time is 60000 milliseconds for 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

    The widget will be installed after you run the application. Drag it to Home screen and you'll have this result:

    I cropped the video to not keep you wait 4 minutes.

Conclusions

    Through 4 parts in this series, I hope you now have general knowledge about developing a widget in Android - which can be understand as an extension of the application. For further reading, check these helpful document and tutorial:

Share


Previous post
« Prev Post
Next post
Next Post »