According to the flutter AppLifecycleState documentation:
resumed → The application is visible and responding to user input
But It seems not to detect app opening.
I have implemented the AppLifecycleState
in the main.dart
:
SystemChannels.lifecycle.setMessageHandler((msg) {
switch (msg) {
case 'AppLifecycleState.paused':
{
function...
}
break;
case 'AppLifecycleState.resumed':
{
function...
}
break;
}
return Future.value();
});
How to check whether an application becomes in Foreground in Flutter (based on resume and app open)?
I don't know why the built in lifecycle management does not provide a app-open event, but this is how we do it.
We define our own enum that replicates the AppLifecycleState
where we add opened
:
/// see [AppLifecycleState] but added [opened]
enum AppState {
opened, // <--
resumed,
paused,
inactive,
detached,
}
Then we define a widget that uses initialState
to trigger the opened
event and use the WidgetsBindingObserver
mixing to detect the other changes.
class AppLifecycleTracker extends StatefulWidget {
final Widget child;
final void Function(AppState state) didChangeAppState;
const AppLifecycleTracker({
Key? key,
required this.didChangeAppState,
required this.child,
}) : super(key: key);
@override
State<AppLifecycleTracker> createState() => _AppLifecycleTrackerState();
}
class _AppLifecycleTrackerState extends State<AppLifecycleTracker>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
widget.didChangeAppState(AppState.opened);
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
AppState s;
switch (state) {
case AppLifecycleState.resumed:
s = AppState.resumed;
break;
case AppLifecycleState.inactive:
s = AppState.inactive;
break;
case AppLifecycleState.paused:
s = AppState.paused;
break;
case AppLifecycleState.detached:
s = AppState.detached;
break;
}
widget.didChangeAppState(state);
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
Then be sure to add it at the very top of the widget tree to prevent it from being re-rendered (otherwise it would trigger the opened
event again:
runApp(
AppLifecycleTracker(
didChangeAppState: (state) => log(state.name),
child: ...,
)
);