I have some doubts about background task, using plugins like background_fetch or workmanager.
I'm writing an app which has some provider organized hierarchically, that fetch and store some data from firebase. Now, i'd like to have a background task that every n minutes, try to call a function of some of these providers to fetch data, and if there is new data, it should show a notification.
I managed to do that only until the app is not terminated. If the app is closed from recent activities, it doesn't work.
Now, the reason for that that i imagined are three:
I made some mistake writing the code and using the plugins.
These plugins should be not used in this way, but because they works on different isolates, they cannot rely on data stored into the app, and when the app is closed they simply cannot execute a function contained in a provider.
I missed some param or config in the manifest or other.
So, my questions are, how can i make it work? And if these plugins are not made for working with data in the app (despite i'm not (of course) updating any UI), is there a way i can manage to do what i'd like to do (so, fetching data using a provider's function), or not?
Just to clarify, i know (i think) i could fetch data directly in the backgroundFetchHeadlessTask(HeadlessTask task) using firebase API, but i'd like to work with my providers, so i can work with caching and not waste reads.
Here some of my code.
Initialization in main
void main() async {
await GetStorage.init('app');
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('wolf2');
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
FirebaseAuth.instance.currentUser;
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
runApp(const MyApp());
}
@pragma('vm:entry-point')
void backgroundFetchHeadlessTask(HeadlessTask task) async {
String taskId = task.taskId;
bool isTimeout = task.timeout;
if (isTimeout) {
print("[BackgroundFetch] Headless task timed-out: $taskId");
BackgroundFetch.finish(taskId);
return;
}
print('[BackgroundFetch] Headless event received.');
BackgroundFetch.finish(taskId);
}
Function called in the first view
Future<void> initPlatformState() async {
int status = await BackgroundFetch.configure(BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
startOnBoot: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: NetworkType.ANY
), (String taskId) async { // <-- Event handler
// This is the fetch-event callback.
print("[BackgroundFetch] Event received $taskId");
listNews.clear();
await Provider.of<ModelDebitsList>(context, listen: false).getNews();
listNews = Provider.of<ModelGroups>(context, listen: false).newsList[Modules.debits] ?? [];
if (listNews.isNotEmpty){
_showNotificationWithDefaultSound(listNews.first.module.name, listNews.first.description);
}
BackgroundFetch.finish(taskId);
}, (String taskId) async { // <-- Task timeout handler.
print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
BackgroundFetch.finish(taskId);
});
print('[BackgroundFetch] configure success: $status');
if (!mounted) return;
}
Provider.of(context, listen: false).getNews(); it's a simple function that fetches some data from firebase and add News, which is a custom class, to a list contained in ModelGroups, which is another provider.
Thanks in advance for any advice or answer. Feel free to ask for more clarification or code.