Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Widget is not updated when app is in terminated state #171

Open
Gummybearr opened this issue Oct 15, 2023 · 3 comments
Open

[Android] Widget is not updated when app is in terminated state #171

Gummybearr opened this issue Oct 15, 2023 · 3 comments

Comments

@Gummybearr
Copy link

Gummybearr commented Oct 15, 2023

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!

@Gummybearr Gummybearr changed the title Widget is not updated when app is in terminated state [Android] Widget is not updated when app is in terminated state Oct 15, 2023
@dishankjindal1
Copy link

Any update on this, did you made it working?

@Gummybearr
Copy link
Author

No. Running background task every 15 min can be an approach, but it is not an elegant way to solve this issue.

@offline-first
Copy link

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 ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants