home_widget
home_widget copied to clipboard
[Android] Widget is not updated when app is in terminated state
Hi, I want to update a widget even when the app is in terminated state, but it seems like it only works when app is on either foreground or background.
This issue might be a duplicate of this one, but I opened up a new issue to provide some code.
android side code
AndroidManifest.xml
<!-- Home Widget -->
<receiver android:name="AppWidgetProvider" 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/task_widget_info" />
</receiver>
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver" android:exported="true">
<intent-filter>
<action android:name="es.antonborri.home_widget.action.BACKGROUND" />
</intent-filter>
</receiver>
<service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true"/>
<!-- Home Widget -->
AppWidgetProvider.kt
class AppWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray,
widgetData: SharedPreferences
) {
appWidgetIds.forEach { widgetId ->
val views = RemoteViews(context.packageName, R.layout.task_widget_layout).apply {
val pendingIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java
)
setOnClickPendingIntent(R.id.widget_root, pendingIntent)
val datetimeToday = widgetData.getString("_datetime_today", "Date is not fetched")
setTextViewText(R.id.datetime_today, datetimeToday)
val refreshIntent = HomeWidgetBackgroundIntent.getBroadcast(
context,
Uri.parse("myapp://update_task_widget")
)
setOnClickPendingIntent(R.id.refresh_button, refreshIntent)
val remainingTask1 = widgetData.getString("_remaining_task1", "Login to fetch data")
setTextViewText(R.id.remaining_task1, remainingTask1)
val remainingTask2 = widgetData.getString("_remaining_task2", "")
setTextViewText(R.id.remaining_task2, remainingTask2)
val remainingTask3 = widgetData.getString("_remaining_task3", "")
setTextViewText(R.id.remaining_task3, remainingTask3)
val remainingTask4 = widgetData.getString("_remaining_task4", "")
setTextViewText(R.id.remaining_task4, remainingTask4)
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
}
flutter side code
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
await HomeWidget.registerBackgroundCallback(
backgroundCallback,
);
runApp(const ProviderScope(child: App()));
}
@pragma('vm:entry-point')
Future<void> backgroundCallback(Uri? uri) async {
if (uri?.host == 'update_task_widget') {
DateTime now = DateTime.now();
Response taskResponse = await getTasksOfDay(now);
if (taskResponse is Error) {
return;
}
List<Task> tasks =
((taskResponse as Success).data as TasksOfDayResponse).tasks;
tasks.sort((a, b) => b.id!.compareTo(a.id!));
List<Task> remainingTasks =
[...tasks].where((e) => e.succeeded == false).toList();
await updateWidget(now, remainingTasks);
}
}
Future<void> updateWidget(DateTime datetime, List<Task> remainingTasks) async {
// update shared preference code now shown for simplicity
await HomeWidget.updateWidget(
name: 'AppWidgetProvider',
iOSName: 'AppWidgetProvider',
);
}
pubspec.yaml
environment:
sdk: '>=3.0.5 <4.0.0'
dependencies:
home_widget: ^0.3.0
I want to update the widget even when the app is closed. I am not using flutter_workmanager since periodic update is not needed at this moment.
Btw, I appreciate your library!
Any update on this, did you made it working?
No. Running background task every 15 min can be an approach, but it is not an elegant way to solve this issue.
Android Home widgets can only be updated once an hour on the most android devices. Alarm Manager is a common method to update them more frequently. The home_widget is working, just wait 30-60 minutes ;)