How to execute some code just before app is swiped off from task list in flutter? - flutter

I want to execute some code(say calling a REST API) just before the App is swiped off the task list. So far I've tried used WidgetsBindingObserver to detect when the app reaches detached state. The connection is lost before reaching the detached state.
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (_lastLifecycleState == AppLifecycleState.detached) {
print('DETACHED!');
}
}

Related

Resuming an app with nested navigation, only restores the child navigation and not the parent

I have an app, where the user can navigate to a 'normal' views, and then a container view with a bottom nav that has it's own navigator. In the normal flow, a user can click a link and the app checks to see if this should be displayed in the container view.
If the container doesn't exist : Create the container, push it on to the parent navigator create the new page in the container, push it on to the local stack.
If the container DOES exist : popUntil the parent navigator until the container page is displayed. Add the page to the container and push that view to the local navigator.
This all works, until the app is paused. When the app resumes if the last paged displayed is in the second case. (When the container widget already exists), the container view is missing, and only the page from the local navigator is displayed. If I press the back button, the last page...Is the same again!
So my question is : When resuming from pause, is there a known/preferred/correct method for restoring parent and nested navigation correctly?
When an app is paused and resumed, the state of the app is usually saved and restored using the saveState and restoreState methods in the NavigatorState object. When you have a nested navigator, you need to make sure that you correctly save and restore the state of both the parent and child navigators.
Here are some tips that you can follow to correctly save and restore the state of your parent and child navigators:
In the parent navigator, save the current route and the child navigator's state when the app is paused:
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
_savedRoute = ModalRoute.of(context);
_savedState = _childNavigatorKey.currentState?.saveState();
}
}
When the app is resumed, check if the saved route is the same as the current route. If they are different, pop the current route and push the saved route:
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
if (_savedRoute != ModalRoute.of(context)) {
Navigator.of(context).popUntil((route) => route == _savedRoute);
_childNavigatorKey.currentState?.restoreState(_savedState);
}
}
}
In the child navigator, save and restore the state in a similar way:
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
_savedState = currentState?.saveState();
}
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
if (_savedState != null) {
currentState?.restoreState(_savedState!);
_savedState = null;
}
}
}
By following these tips, you should be able to correctly save and restore the state of both the parent and child navigators, and ensure that the correct views are displayed when the app is resumed.

How to check if App is not being used while in Foreground in Flutter?

In my flutter app, I wanted to check if a user is not using the app while they are in Foreground. WidgetsBindingObserver only checks if the app is in the foreground/background. and if the app has resumed, inactive, detached, or paused. but how can I check if the user is not using the app in the foreground at a specific time?
#override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance!.addObserver(this);
}
#override
void dispose() {
// TODO: implement dispose
WidgetsBinding.instance!.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.detached ||
state == AppLifecycleState.inactive) return;
final isBackground = state == AppLifecycleState.paused;
final isForeground = state == AppLifecycleState.resumed;
if (isBackground || isForeground) {
Get.offAll(Login());
}
}
You need to run a periodic timer that gets reset whenever the user taps the screen.
So set up something global to do just that. Set it to X seconds and reset to 0 when the user tap is detected. If the timer reaches Y seconds you know that it is not used by the user.
Flutter - Detect Tap on the Screen that is filled with other Widgets
https://blog.logrocket.com/understanding-flutter-timer-class-timer-periodic/
Hopes this helps you in the right direction

Flutter Make api call when home button(middle android button) is pressed and user comes back on app

In my app i have screens that fetched data from the Api, and sometimes the backend can update or change something on the api, so if the user is using the app, and the user presses the home button (middle android button. the circle) and comes back to the app later, i dont see the data being updated so no api call is being made, but when i press the back button and come back to the app the api call is being made same as when i close the app and remove it from the opened app history and open it again, the api call is being made, so i need that to happened the same when the home button is pressed, the user gets out the app by pressing the home button, comes back and the api call will be made. I looked in to it and i was told i need to use WidgetsBindingObserver class. Any help would be appreciated, let me know if you need any code to post.
i tried this but it wont work
class _StopWorkingScreenState extends State<StopWorkingScreen>
with WidgetsBindingObserver {
late Future<Response> futureDataForStatus;
#override
void initState() {
super.initState();
futureDataForStatus = getLocationStatus();
WidgetsBinding.instance!.addObserver(this);
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.inactive:
print("Inactive");
break;
case AppLifecycleState.paused:
print("Paused");
break;
case AppLifecycleState.resumed:
futureDataForStatus;
break;
}
}
You need to call the function in your switch operator, not just pass a variable.
You could do something like:
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
...
case AppLifecycleState.resumed:
setState(() {
futureDataForStatus = getLocationStatus();
});
break;
}
}
This will update the state on opening of the app and reload the view with new data (assuming you are using futureDataForStatus as future of a FutureBuilder somewhere on the page.

How can i firestore stream snapsnot pause

I have a structure made up of tabs. I'm listening which tab you're in. I am using AutomaticKeepAliveClientMixin in tabs
late StreamSubscription _subscription;
#override
void initState() {
super.initState();
_subscription = FirebaseFirestore.instance
.collection('users')
.doc(id)
.snapshots().listen((DocumentSnapshot snapshot) => _onUpdate(snapshot));
widget.tab?.addListener(_tabListener);
}
#override
void dispose() {
_subscription.cancel();
widget.tab?.removeListener(_tabListener);
super.dispose();
}
_tabListener () {
if(widget.tab?.page == 0.0) {
if(_subscription.isPaused) {
_subscription.resume();
}
} else {
_subscription.pause();
}
}
No problem so far, it stops listening and picks up where it left off, but when it starts again it brings all the changes that happened when it stopped.
Keeps sending snapshot changes constantly in the background.
I want the stream to stop completely when the tab changes, and start over when it comes to tab, how can I do that?
According to the StreamSubscription pause method documentation, if the subscription receives events while paused they will be buffered until the subscription is resumed.
As explained in this paragraph the recommended solution to avoid buffering events would be to cancel the subscription and start it again when needed.

Flutter-background process

I have a question about background process in flutter. The app I am building needs to constantly work in the background and use live accelerometer data. I have been over many libraries and tutorials, but I just can find something which will work constantly in the background. I used the flutter_background_servicepackage and there is a notification on the top of the screen which says "background service- preparing." Any suggestions?
void onStart() {
WidgetsFlutterBinding.ensureInitialized();
final service = FlutterBackgroundService();
service.setForegroundMode(false);
}
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.inactive ||
state == AppLifecycleState.detached) return;
final isBackground = state == AppLifecycleState.paused;
if (isBackground) {
number=1;
}
else{
number=0;