Lesson 122. Widgets. Previews, resizing, lock screen, manual updates

Lesson 122. Widgets. Previews, resizing, lock screen, manual updates


In this lesson:

– Consider other features of the widget: previews, resizing, lock screen, manual updates

In the past lessons, we covered all the highlights about widgets. It remains to talk about a few small but useful opportunities.

I will not create a separate project for this, I will show only code snippets and screenshots. The lessons learned in the previous lessons should be sufficient to understand what is being said.

previews

(Level 11 API)

When you want to add a widget, you open the selection screen and see a list of widgets with names and pictures there. By default, a program icon is used instead of a picture. And you can put your own image there.

I’ll make a simple widget that shows the time when updating

My widget is called WidgetFeatures and in the widget list it looks like this:

The preview image now uses the program icon and is not very informative.

Let’s put our picture. I will make a screen home screen with my widget, then crop the image to this state

I will throw it in the res / drawable folder and write it in the metadata file of the widget

android:previewImage="@drawable/screen"

The list widget will now look like this:

And the user has a rough idea of ​​what the widget will look like after installation.

resize

(API Level 12)

You can allow the user to resize the widget.

To do this, you must specify in the metadata:

android:resizeMode="horizontal|vertical"

In this case, the widget will be able to resize both vertically and horizontally. If you only need one direction, leave it alone in the attribute value.

You can stretch the widget to the extent that it will allow free space on the screen. But you won’t be able to make it smaller than the size you originally specified minHeight and minWidth.

To do this in Level 14 API two more metadata attributes appear: minResizeWidth and minResizeHeight. They just set the minimum values ​​for resizing the widget, and the minHeight and minWidth attributes become the default values ​​and are used to specify the initial size of the widget when added.

IN Level 16 API the onAppWidgetOptionsChanged method appears in the ISP class. The method works when you resize the widget. It provides you with a Bundle with data (type – int, units – dp) about the new size. The data can be obtained using these keys:

OPTION_APPWIDGET_MIN_WIDTH
OPTION_APPWIDGET_MIN_HEIGHT
OPTION_APPWIDGET_MAX_WIDTH
OPTION_APPWIDGET_MAX_HEIGHT

As the name of the variables shows, the system returns not the exact value of the new width or height of the widget, but the range with the minimum and maximum values. I do not know how these values ​​are formed, but we are encouraged to use them to adjust the contents of the widget to new dimensions.

For example, I will output these numbers in the widget.

Here is a widget with a width of two cells and a height of one (2×1).

And here is what will happen if it is stretched to 3×2

Stretch to 4×3

The current size of the widget can also be obtained using the getAppWidgetOptions method of the AppWidgetManager class. It will return the Bundle with the same settings.

lock screen

(API Level 17)

Attribute widgetCategory can determine the location of the widget not only in Home (home_screen), but also on the lock screen (keyguard).

android:widgetCategory="home_screen|keyguard">

In this case, the widget will appear in the list of widgets for the lock screen

And after adding it will be visible

To programmatically determine where the widget is located, use the getAppWidgetOptions method again. It will return to you a Bundle from which the OPTION_APPWIDGET_HOST_CATEGORY key can be extracted a category (int type). It can be either WIDGET_CATEGORY_HOME_SCREEN (home) or WIDGET_CATEGORY_KEYGUARD (lock screen).

In metadata, you can also specify the layout used for the widget on the lock screen. this is an attribute android: initialKeyguardLayout. similar to the attribute android: initialLayout you specify the layout file there. However, for some reason it did not work for me and the lock screen widget used the same layout as the Home screen widget. I didn’t understand why.

Manually update widgets

Typically, the system itself sends broadcast messages that it’s time to update the widget, and the minimum threshold it allows you to set is half an hour. We can get around this and schedule our schedule. There are several options for how to organize it and where to call it. I’ll show one of them.

All this is done in the provider’s class.

Create a variable:

final String UPDATE_ALL_WIDGETS = "update_all_widgets";

We next write in the methods onEnabled and onDisabled:

  @Override
  public void onEnabled(Context context) {
    super.onEnabled(context);
    Intent intent = new Intent(context, MyWidget.class);
    intent.setAction(UPDATE_ALL_WIDGETS);
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    AlarmManager alarmManager = (AlarmManager) context
        .getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),
        60000, pIntent);
  }

  @Override
  public void onDisabled(Context context) {
    super.onDisabled(context);
    Intent intent = new Intent(context, MyWidget.class);
    intent.setAction(UPDATE_ALL_WIDGETS);
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    AlarmManager alarmManager = (AlarmManager) context
        .getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(pIntent);
  }

The content of the two methods is almost identical, only the first starts sending a broadcast message every minute with AlarmManager, and the second cancels it.

In the method onReceive we write:

  @Override
  public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    if (intent.getAction().equalsIgnoreCase(UPDATE_ALL_WIDGETS)) {
      ComponentName thisAppWidget = new ComponentName(
          context.getPackageName(), getClass().getName());
      AppWidgetManager appWidgetManager = AppWidgetManager
          .getInstance(context);
      int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
      for (int appWidgetID : ids) {
        updateWidget(context, appWidgetManager, appWidgetID);
      }
    }
  }

where updateWidget is your method that spells out the logic of updating the widget.

Here we catch the broadcast, which sends AlarmManager every minute. Next, we create a ComponentName corresponding to the widget provider of our application and, using it, get a list of widget IDs using the getAppWidgetIds method. This list is then driven through the upgrade method.

And don’t forget to put the updatePeriodMillis = 0 attribute in the metadata to disable broadcast broadcasting from the system for the widget.

Thus, we have set our update schedule. It will turn on when you create the first instance of the widget (or at system startup if there are instances of the widget) and will shut down when you delete the last instance.

In the next lesson:

– create keys and sign the application




Discuss in the forum [9 replies]

Leave a Comment