Introduction to Android widgets

If you’ve ever used a smartphone (and I’m sure you have), you must have come across a widget and even used it.

App Widgets are miniature application views that can be embedded in other applications (such as the Home screen) and receive periodic updates.

So whether you want info on the weather (pun intended), or the current time in another state, or up-to-date exchange rates of your favorite currencies, an app widget can help display that information directly on your home screen.

Creating a simple home screen widget in android

When creating a widget, the following entities are needed:

  1. An AppWidgetProvider class implementation
  2. An XML AppWidgetProviderInfo object
  3. A view layout
  4. An app widget configuration activity (optional)

We would go through each entity one after the other and understand what they’re all about.

  1. AppWidgetProvider class:

    This class allows you to blend your app widget, with simple methods that you can use to perform actions when your widget is updated, enabled, disabled, or deleted. It is based on broadcast events i.e the android system sends a “signal” or broadcast when such events occur, and you can do what you want to do based on that. This class extends the BroadcastReceiver to handle the widget broadcasts and the following are some of the methods that can be called:
    onEnabled()
    onDeleted()
    onDisabled()
    

More often than not, you would only need to call the onUpdate method when creating a basic widget, but the others could come in handy in complex situations.

Here’s a code sample that shows how a basic widgetprovider class may look:

class ExampleAppWidgetProvider : AppWidgetProvider() {
    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each App Widget that belongs to this provider
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity
            val pendingIntent: PendingIntent = Intent(context, ExampleActivity::class.java)
                    .let { intent ->
                        PendingIntent.getActivity(context, 0, intent, 0)
                    }

            // Get the layout for the App Widget and attach an on-click listener
            // to the button
            val views: RemoteViews = RemoteViews(
                    context.packageName,
                    R.layout.appwidget_provider_layout
            ).apply {
                setOnClickPendingIntent(R.id.button, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current app widget
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

When this class is created, you have to add your widget to you manifest file like so:

<manifest>
...
  <application>
    ...
    <receiver android:name="MyAppWidgetProvider">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data android:name="android.appwidget.provider"
                   android:resource="@xml/my_appwidget_info" />
    </receiver>
  </application>
</manifest>

Notice that in the <receiver> element’s name attribute, we specify our AppWidgetProvider class name. and in the “android: resource” attribute, we specify our app widget info XML entity which we would talk about in a bit.

  1. AppWidgetProviderInfo XML:

    This XML file states the qualities of our app widget, like the layout dimensions, the layout resource, how often to update the widget, and the configuration activity to launch when the widget is created (if any). We would talk about configuration activities later on. We create this file in an xml folder which is in our project res folder, we define all attributes in a single <appwidget-provider> element like so:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:updatePeriodMillis="86400000"
    android:previewImage="@drawable/preview"
    android:initialLayout="@layout/example_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigure"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen">
</appwidget-provider>

As you can see, we set a preview image for our widget, we point to the configuration activity using the “android: configure” attribute, we set the widget category (in this case, home_screen) and we also point to the initial layout of the widget which we would talk about next.

  1. The WidgetLayout:

    Unless you’re new to android development, you must have used layouts in your android apps. Widget layouts are no different from the conventional layouts that we all know, you define the layout in XML as usual and save it in the res/layout/ directory, with all your other XML files. Creating the layout proper is also no biggie, but we should note that not all layouts or view groups are supported when creating a widget. This is because App widget layouts are based on RemoteView A remote view is a class that indicates view hierarchies that can be displayed in another process entirely. They are mostly used for notifications and widgets. Here are some of the views and layouts that remote views support: FrameLayout, LinearLayout, RelativeLayout, GridLayout, Button, ImageView, TextView, ListView, GridView, ProgressBar, etc. Here’s a sample layout code for an app widget:
<FrameLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:padding="@dimen/widget_margin">

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:background="@drawable/my_widget_background"></LinearLayout>

</FrameLayout>

Not so different from your conventional activity XML.

  1. ConfigurationActivity:

    This optional activity is used when you’d like your user to set up some stuff before pinning the app widget. It is automatically launched when the widget is created (when you drag the widget to the home screen or pin directly from the app). The user can configure things like widget color, size, update period, or other settings. This configuration activity is declared like a regular activity in the android manifest file but it would be launched with the ACTION_APPWIDGET_CONFIGURE action. Here’s a sample of the manifest declaration:
    <activity android:name=".ExampleAppWidgetConfigure">
     <intent-filter>
         <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
     </intent-filter>
    </activity>
    
    If you recall, we also pointed to this activity in our AppWidgetProviderInfo XML file, using the “android: configure” attribute (see no 2 for info). That’s all the necessary setting you need to implement for your configuration activity, now, you should create the actual activity and implement all your intended functionalities.

There are a lot of things that can be done with App widgets and only the basics are stated in the article, more complex widgets can be created like collection widgets, and you can perform more actions with your widgets too. The docs are well written and you should get the hang of it after understanding these basics. Check them out here

I hope you’ve picked a thing or two from this write-up!😇 Leave a like and comment if you have any questions. Thank you!