Setting Up home_widget in Flutter [android — XML/Glance]

Gagan Bhirangi
4 min readDec 11, 2024

--

Let’s dive into the world of interactive Android widgets! Today, we’ll start by setting up everything needed to create sleek and functional widgets for Android devices using Flutter.

We’ll use home_widget package to make the implementation of widgets simpler.

flutter pub add home_widget

Setup

We can develop widgets using XML or Jetpack glance

  • Using XML

1. Open the Android module in Android Studio.

2. Right-click on ‘app’ -> New -> Widget -> App Widget

3. Fill desired details in a prompt

You can modify these options later also.

4. After creating the widget you may get an error of Kotlin Gradle plugin version

> Cannot resolve external dependency org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22 because no repositories are defined.

Go to android > build.gradle and comment/remove the mentioned plugin version, and run the Flutter project once —

dependencies {
// classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22'
}
  • ensure you are using minSdkVersion 21

5. Android Studio will create the necessary files for creating the widget, from those, let’s move the Implementation of App Widget functionality (AppWidgetDemo.kt) file from app -> main -> java to the folder com.example.demo.home_widget_demo which is under kotlin folder

6. In AppWidgetDemo.kt change AppWidgetProvider with HomeWidgetProvider class. Also, pass SharedPreferences (to interact with data in flutter) as shown —

7. Finally, run the Flutter project, and you will be able to see the widget option for your app

8. To launch the app by clicking the widget, open AppWidgetDemo.kt and in the updateAppWidget function, add apply() { ... } to RemoteViews() as shown below.
[ here, I’m targeting click, which will be on text using
R.id.appwidget_text ]

val views = RemoteViews(context.packageName, R.layout.app_widget_demo).apply() {

val pendingIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java)
setOnClickPendingIntent(
R.id.appwidget_text,
pendingIntent
)

}
  • Using Glance

1. In android/app/build.gradle add dependencies —

dependencies {
implementation "androidx.glance:glance:1.1.1"
}

In the same build.gradle, Activate compose compiler by adding following

android {
...
buildFeatures {
compose true
}

composeOptions {
kotlinCompilerExtensionVersion = "1.4.8"
}
...
}

for the latest version refer release page.

2. Define simple app widget and info of that widget in app_widget_demo.xmlinside xml folder

Example code —

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout"
android:minWidth="100dp"
android:minHeight="100dp"
android:resizeMode="none"
android:updatePeriodMillis="500"
android:widgetCategory="home_screen">
</appwidget-provider>

3. Let’s code a simple app widget with a glance. Create the Kotlin file AppWidgetdemo.kt in kotlin folder of the app

package com.example.home_widget_glance

import android.content.Context
import androidx.glance.appwidget.GlanceAppWidget
import androidx.compose.runtime.Composable
...

class MyAppWidget : GlanceAppWidget() {

override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
// add your own widget here
MyContent(context)
}
}

@Composable
private fun MyContent(context: Context) {
Box(
modifier = GlanceModifier.background(Color.White).padding(16.dp)
.clickable(onClick = actionStartActivity<MainActivity>(context))
) {
Column(
modifier = GlanceModifier.fillMaxSize(),
verticalAlignment = Alignment.Vertical.CenterVertically,
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
) {
Text(
"Hello Flutter!",
style = TextStyle(
fontSize = 32.sp,
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
),
)
}
}
}
}

4. Make AppWidgetDemoReceiver.kt in the same folder, which will handle updating behaviour of the widget.
home_widget provides an abstraction for this, so we only need to provide simple references to the Widget

package  com.example.home_widget_glance

import HomeWidgetGlanceWidgetReceiver

class MyAppWidgetReceiver : HomeWidgetGlanceWidgetReceiver<MyAppWidget>() {
override val glanceAppWidget = MyAppWidget() // pass created widget here
}

5. Now, Registering the MyAppWidgetReceiver in our AndroidManifest.xml file and the associated metadata file

<application>
...
<receiver android:name=".MyAppWidgetReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/app_widget_demo" />
</receiver>
...
</application>

6. Run the Flutter project, you’ll be able to see the widget option for the app

Setup is Done!

That’s all for now. Thank you for reading this article👏

See you next time 👍.

--

--

Gagan Bhirangi
Gagan Bhirangi

No responses yet