Exploring and Building Android App Widgets With Glance APIs
Create intuitive Android widgets
According to the Android developers website, app widgets are miniature applications that can be embedded in other applications(for example, the home screen).
For some time now, I have been experimenting and building a few apps with the new Jetpack Compose toolkit.
Jetpack Compose has streamlined development time significantly for me and this is a big win. To make things better, there has been the introduction of what is referred to as the Glance API.
With the old Android View system, we built app widgets using XML, while with Glance, we use the same knowledge we have gotten from Jetpack Compose and we build the Android app widgets in Kotlin code. How cool is that? Let me show you how to implement android app widgets using Glance.
Setting Up the Dependency
First things first, create a project in Android Studio and choose the Jetpack Compose template project. Then next, add the glance dependency in your app-level build.gradle
file as follows;
implementation "androidx.glance:glance-appwidget:1.0.0-alpha02"
Next, ensure that you sync your project and you are good to go. The glance dependency gives us access to Glance’s own composables such as Column, Row, etc. When building the app widgets, ensure that your imports are from androidx.glance
.
The Glance composables behave almost similar to Jetpack Compose specific Composables. We will build a sample weather app widget with static data that looks like the one in the emulator screenshot below.
Define app widget provider info in XML
You probably thought everything here will be replaced with Kotlin, but well, same as with the old view system, you will have to define the app widget provider using XML.
Ours will be as simple as the one below.
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minHeight="180dp"
android:minWidth="180dp"
android:description="@string/app_widget_description"
android:previewLayout="@drawable/example_appwidget_preview"
android:minResizeHeight="90dp"
android:minResizeWidth="90dp"
android:targetCellHeight="2"
android:targetCellWidth="2"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"
/>
The AppWidgetProviderInfo
information above is gotten by creating an xml
resource and giving it the name you chose(it should be in the res/xml
directory). I named this one my_widget_provider.xml
. We define several attributes like the minHeight
, minWidth
, previewLayout
, etc. Android 12 brings new attributes like targetCellWidth
and targetCellHeight
.
Creating the Glance Widget
The next thing for us to do is to create the actual widget. This is done by extending the GlanceWidget
abstract class from androidx.glance.appwidget
, and override the most important method called Content
.
Content is marked with the @Composable
annotation and it is here that we define what our widget layout will look like. We will start with a composable which is simply a column named DayItem
Note the difference from our normal composables. Here, Modifier
is replaced by GlanceModifier
. The imports are from androidx.glance
.
Next, let us do the actual work by extending the GlanceAppWidget
class.
The most important thing as I said is for us to extend the GlanceAppWidget
class and override the Content
method which is marked with @Composable
.
The next thing for us to do is to extend GlanceAppWidgetReceiver
and override the value for glanceAppWidget
and return our GlanceNewWidget
The next thing for us to do is to register our receiver in the AndroidManifest file.
Ensure that you register the receiver as a child of the application tag. In the meta-data
, we specify our provider XML file.
This should be enough for us. Run your application and long click on an empty section of the screen and select Widgets
, and look for the name of your app and drag the widget to the screen. You should see what looks like what we have in the above screenshot.
Note that it is not some sort of magic. These composables are transformed to RemoteViews
.
Invoking actions With Glance
The purpose of your app widget might be that when some portion or button is clicked, something happens like starting an activity, a service or maybe just saving something to the database.
Glance provides us with actions to perform and we can create our own actions. By default, there are actions for starting an activity, a service, a broadcast receiver and others.
Okay at this point, let us say we want to launch a new activity NewActivity
when 32
° is clicked and we pass an extra called name and receive it in NewActivity
.
How do we do this? For this, we will apply GlanceModifier.clickable
and pass an action to it. Thus the Text
becomes:
The method actionStartActivity
takes an intent
and a parameters
parameters. In the parameters, we pass the data we want to pass to the activity. In this case, we give it the key ActionParameters.Key<String>("name")
and the value Lionel Messi
. Below is how we will receive it in NewActivity
If you run the app now and create a widget and click on the text, it will launch the NewActivity
. You will see the text Lionel Messi
. That is how you can pass data to activities using actions.
For now, this is the simplest way of creating app widgets using composables rather than XML. There is a lot that you can do but I will leave that for you to do some research.