Flutter: Executing a Task after App is Killed - flutter

I would like to execute some asynchronous code just before my Flutter App is killed by the OS due to low memory.
I am currently using the WidgetsBindingObserver mixin to listen to app lifecycle changes, and when the app is paused (before it is detached) start the code execution.
The code I'm trying to execute:
I am trying to commit something to a local cache using SharedPreferences, but to no avail. It doesn't end up committing the data.
The Potential Issues:
I'm not sure if it is primarily due to running code while the app is being detached - in which case it could be solved by using the WorkManager package.
Or, if it is related to accessing Shared Preferences after the app has already been detached.
Any help or insight would be welcome!

Unfortunately, using the WidgetsBindingObserver mixin doesn't work for my use-case. When the lifecycle status changes to detached, any asynchronous code executed after this is not able to complete in time.
I solved the problem using a local key-pair store called Hive to locally save the form data as it was inputted by the user. Then, when they are ready to resume the form completion, re-populate the form and allow them to continue filling it out.

Related

Ensuring Completion of Operations During app Termination in Flutter

Let's say we have a Flutter app where we want to save some persistent data using shared preferences.
(We don't want to save the data persistently every time the user changes it because the UI depends directly on the data, and in order to save it we need to use await async, and that lags the UI), so we use WidgetsBindingObserver to detect when the app goes to the background in order to use that event as an efficient catch-all opportunity to save the data.
So, we have some code like this in the root page of our app:
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.paused) {
// went to Background
myPersistentData.instance.write(); // <-------------- this is an async operation
}
if (state == AppLifecycleState.resumed) {
// came back to Foreground
}
}
This seems to work, but I'm concerned that the lifecycle could progress beyond "paused" (pause>stop>finish) so quickly that this "trailing" operation doesn't have time to finish... and thus the data would not be saved.
Is this a legitimate concern?
I would say as much as possible try to avoid calling async operations in the dispose or lifecycle methods of widgets, while you may be concerned that it may/may not complete i would recommend like the dart docs states here: https://api.dart.dev/stable/2.14.1/dart-async/unawaited.html, "Not all futures need to be awaited.", "You should use unawaited to convey the intention of deliberately not waiting for the future.". But generally, i'd avoid calling async functions in these methods.
It should be a concern for sure because the time available for an app to run in background is limited and not defined.
Based on the memory resources needed for the most important app, which is the one in foreground, the system may kill your app faster or at a later point in time. In either scenarios you don't have much time to complete the tasks, this event should be used to do fast clean up like killing tasks that are started, clearing token or maybe saving a token or a session info.
There are also scenarios which will cause problems for this approach, like the pone runs out of battery or the OS crashes, in this case you don't have any notification of app going into bg. Or the user force quits your app.
In your case, I would say you have another concern, saving data in shared preferences shouldn't affect your UI only if:
you save it synchronously which is a no no
you save a huge chunk of data in shared prefs, in this case you should use a database.
and a less likely scenario, you have a race condition while you save in shared prefs which are not thread safe.
I would suggest to rethink a bit your approach on this matter, maybe you can spawn async operations that save the data in certain points of the app (user exits a screen or whatever) while also keeping a copy in memory. Maybe is better to save it using a database. In the end is your decision, but my advice would be, don't rely on the app running in bg time.
For something like this, there is no way you can continue a service purely in Flutter. That's bummer of course but there are work-arounds you can use to do that.
If you want to approach this problem in a more convenient but difficult way, you can always create a service in native (Kotlin/Java in case of Android or Swift/Objective-C for iOS) and call your native functions using MethodChannels. Your native service can be alive even if you kill your app. Think of Push-notifications service where even if you kill your app, Push service is always alive to serve your notification.

Flutter Application : Location fetch in background

I want to keep my application running or a piece of code which can perform some operation like getting a current location and call an API to submit that location.
I saw the background_fetch plugin but it says, app can not fetch the callback before 15 minutes in background so it is not feasible solution for tracking a location to get location every 15 minutes, so is there any way that can make possible to keep running some code in background.
Any leads would be appreciated.
Thanks
In flutter, code can be executed in background using Isolates
Isolates are Dart’s model for multithreading, though an isolate differs from a conventional thread in that it doesn’t share a memory with the main program.
Check this post for more info.
Now officially there is some plugins for background location tracking. check out below links:
background_Locations
background_location

First app start failed if there are some events in event store

I started an app with some events in event store. As I understand, read model building starts on first read model request. But of course on first start it is no ready yet, but state is returned instantly. So on the client side on each first page open after a server refresh I have an incorrect state that break down my client app.
My question is how can I avoid getting stale data on the client if read model is still being rebuilt?
At the moment, reSolve read model has no information if it is still building, therefore query resolver just use the current state of the read model, whatever it is.
Currently there is no way to wait for rebuild to finish, or to throw an error.
We've recorded an issue and will fix this in the future release.

Android Async Task does not update UI when application is in background

The application I am working on downloads and parses a large xml file to populate UI elements, namely search and a spinner. This is done through an async task. If the user decides to switch out of the application during this, the information is downloaded correctly, but then when the application is resumed, the UI will not be updated.
Is this because the changes can't be made while the application is not active? What is the best way to go about checking whether the UI was not updated on resume? Or instead should I be doing something with the Async task, checking whether the UI thread is available? I'm having a hard time debugging this because it involves leaving the application which ends the debugger.
You can achieve this scenario through the broadcast receive.
Follow the step:
Solution 1:
Step 1;
Register the broadcast receiver before executing the Asyntask.
Step 2:
send Broadcast in onPostExecute method of Asyntask.
step 3:
And then you can able receive your broadcast message in your activity.
and do whatever you want.
Solution 2:
Otherwise you can use Interface Call back for this Scenario.
Hope It will help you.
It should'nt. App being in background means View objects may or may not be there. Actually the entire process may be stopped or just deleted by android.
Use a Service to truly do processing in background. When processing is complete but UI is not there, post a notification to let user know, OR, save the results and provide it to UI the next time it binds to your service and ask for same thing (a.k.a caching).
The application in background may not be live. The O.S may destroy it in case of memory constrains.
The trick is to try an alternate logic.
When the application moves from background to foreground onresume() is called ,you could try saving the data to db and update the content on the resume call.
FYI.onPause() and OnResume() is called when the application goes background and foreground respectively.

Can Android 'kill' an Activity without killing the application?

As we know, the default flow in Android for such scenario is calling the activity's respective onSaveInstanceState, onStop, onDestroy methods before releasing the reference to the Activity object.
However it appears I have a case when my application is on the background, the activity gets killed without those methods being called, but my application itself does not get destroyed.
However I am unable to force-reproduce this. Whenever I use applications on the foreground that require a lot of resources, the whole process gets killed, not just the activity.
Which kind of makes me wonder, because I believe the 'app killing' on low resources is essentially just the old signal way, does the Android system actually 'kill' (release) an activity instantly without calling these methods? Or am I chasing ghosts?
Android app out of memory issues - tried everything and still at a loss
This is not how things work. The only memory management that impacts activity lifecycle is the global memory across all processes, as Android decides that it is running low on memory and so need to kill background processes to get some back
Now the explanation in the official documents is more clear
The system never kills an activity directly to free up memory. Instead, it kills the process in which the activity runs, destroying not only the activity but everything else running in the process, as well. To learn how to preserve and restore your activity's UI state when system-initiated process death occurs, see Saving and restoring activity state.
It is possible Android OS kills only some of your activities even if your app is in foreground. For instance if you have two activities A and B, and when A calls startActivity / startActivityForResult to start activity B then Android may deceide to destroy activity A's instance because it is taking up too much memory space.
You can force killing activities which don't run in the foreground by checking Don't keep activities in developer options menu.
Does the Android system actually 'kill' (release) an activity
instantly without calling these methods?
Yes it does. Here's what the docs say in regards to onStop():
Note that this method may never be called, in low memory situations
where the system does not have enough memory to keep your activity's
process running after its onPause() method is called.
and in regards to onDestroy():
There are situations where the system will simply kill the activity's hosting
process without calling this method (or any others) in it, so it
should not be used to do things that are intended to remain around
after the process goes away.
Do not count on this method being called as a place for
saving data! For example, if an activity is editing data in a content
provider, those edits should be committed in either onPause() or
onSaveInstanceState(Bundle), not here.
"However I am unable to force-reproduce this." - you could reproduce this situation by sending your application in background and then using the DDMS to kill the process manually.