Flutter : AppLifecycleState not work if devices in locked screen - flutter

I use AppLifeycleState to detect Behaviour my app when the user using it. For detect my app not being used, i used
AppLifecycleState.paused
AppLifecycleState.inActive
AppLifecycleState.detached
Because i want detect if my App not being used for 1 second, i throw user to Confirmation Fingerprint (Like Whatsapp). Everything is fine i can detect if my app not being used if user press recent app, Home button and throw user to Confirmation Fingerprint if user comeback again.
But the problem is , When devices screen in locked up then it opened again , user not throwing to Confirmation Fingerprint.
I surely can see in console my app is AppLifecycleState.paused and AppLifecycleState.inActive, but strangely if I hot reload ctrl +s in my IDE my app throwing me to Confirmation Fingerprint.
Why can be like this ?
Working 1
Working 2
Not Working !
Already tested too in real Device (Redmi Note 4) , and still not working.
Source Code AppLifecycleState
#override
void didChangeAppLifecycleState(AppLifecycleState state) async {
setState(() => _appLifecycleState = state);
if (widget.userBox == null) {
print('Box User Null');
return;
} else {
if (widget.userModelHive.fingerPrint || widget.userModelHive.pinCode) {
if (_appLifecycleState != AppLifecycleState.resumed) {
//? Berarti Lifecylenya InActive , Paused , Detached , Maka Simpan Waktu Keluarnya
final actionBox = await repository.changeDateExit(
userModelHive: UserModelHive()
..id = widget.userModelHive.id
..giverName = widget.userModelHive.giverName
..pinCode = widget.userModelHive.pinCode
..fingerPrint = widget.userModelHive.fingerPrint
..darkMode = widget.userModelHive.darkMode
..tokenExpiry = true
..durationToken = widget.userModelHive.durationToken
..dateExit = DateTime.now()
.add(Duration(seconds: widget.userModelHive.durationToken)),
);
print(state);
return actionBox;
} else {
print('Resumed Lifecycle');
}
}
}
if (mounted) {
setState(() {});
}
super.didChangeAppLifecycleState(state);
}

Related

flutter firebase onclick redirection when app is open

in my app firebase push notification is implemented.
on click event works when app is terminated.
but how to achieve notification on click of redirection when app is open.
class _Application extends State<Application> {
// It is assumed that all messages contain a data field with the key 'type'
Future<void> setupInteractedMessage() async {
// Get any messages which caused the application to open from
// a terminated state.
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
// If the message also contains a data property with a "type" of "chat",
// navigate to a chat screen
if (initialMessage != null) {
_handleMessage(initialMessage);
}
// Also handle any interaction when the app is in the background via a
// Stream listener
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
}
void _handleMessage(RemoteMessage message) {
if (message.data['type'] == 'chat') {
Navigator.pushNamed(context, '/chat',
arguments: ChatArguments(message),
);
}
}
#override
void initState() {
super.initState();
// Run code required to handle interacted messages in an async function
// as initState() must not be async
setupInteractedMessage();
}

How to handle redirects from initState in Flutter

I am using the plugin flutter_local_notifications to show a user notifications on the app. I have managed to show the notifications on the app and the user can click on the notifications, the user will be redirected to see all pending items from the notification in a notification page. I have set the function to detect the onclick on initstate. The whole function and method to show notification I have implemented it on the homescreen.
#override
void initState() {
super.initState();
initPlatformState();
getNotifications();
NotificationApi.init(initScheduled: true);
init();
_configureSelectNotificationSubject(); //function to redirect to Notifications page
}
which goes to
void _configureSelectNotificationSubject() {
print("clicked is the notification");
NotificationApi.onNotifications.stream.listen((String? payload) async {
await Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => WANotifications(current: current)),
(Route<dynamic> route) =>
true);
});
}
The challenge am facing with this implementation is that when a user clicks to go to the home screen , the user gets redirected automatically to the notifications page from the home screen without his/her consent. The redirect should only occur when they click on the notifications.
How can I set the redirect to only occur when the user clicks the notification only and not when they click to go to home screen
You can achieve this with the help of didNotificationLaunchApp.
bool get didNotificationLaunchApp =>
notificationAppLaunchDetails?.didNotificationLaunchApp ?? false;
// Use here,
if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
selectedNotificationPayload = notificationAppLaunchDetails!.payload;
initialRoute = SecondPage.routeName;
}
Pl check full example here : https://pub.dev/packages/flutter_local_notifications/example
For non main file :
#override
void initState() {
super.initState();
localNotification(); // call below localNotification() here.
}
localNotification() async {
final NotificationAppLaunchDetails? notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin!.getNotificationAppLaunchDetails();
if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
// redirect to new screen if true.
}
}

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;

Flutter Riverpod: Refresh Page Offscreen using State Notifier

I'm using StateNotifier and Riverpod.
I have a notification page, which contains a list of notification. When a notification arrives, I trigger a refresh for notification. However, when I navigate to notification page, it still using the old (cached?) list.
How do I refresh a page offscreen?
Foreground Message
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
_localNotification.showLocalNotification(message);
ProviderContainer().read(notificationProvider).getNotification();
});
Background Message
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
final LocalNotification localNotification = LocalNotification();
await localNotification.init();
localNotification.showLocalNotification(message);
ProviderContainer().read(notificationProvider).getNotification();
}
NotificationProvider
Future<void> getNotification() async {
try {
state = const NotificationLoadingState();
_notificationList = await _notificationRepository.getNotification();
state = NotificationLoadedState(_notificationList); // ==> I get a new list here
} catch (e, s) {
state = const NotificationErrorState('error fetching notification');
}
}
UI
final state = watch(notificationProvider.state);
if (state is NotificationLoadingState) {
return _buildLoading();
} else if (state is NotificationLoadedState) {
return _buildLoaded(state.notificationList); // ==> I still get the old list here
} else if (state is NotificationErrorState) {
return _buildError(state.message);
}
Edit:
I managed to solve the foreground message handler by using navigatorKey.currentContext.
However, I still haven't solved background message handler.
I've tried changing my main.dart to use UncontrolledProviderScope with a global ProviderContainer, which then was called from background message handler. It's still not refreshing.
With this line you are creating a new instance for your providers :
ProviderContainer().read(notificationProvider).getNotification();
you need to use a context to get the existing instance of ProviderContainer:
context.read(notificationProvider).getNotification();
or if you are not inside ui make dependencies between your providers

Skipped x frames! The application may be doing too much work on its main thread. What does this error signify and how to solve this?

I'm trying to do authentication with firbase in my Flutter app. Once the user is signed in and goes to the Authenticted screen, this error shows up.
I'm using google_signin plugin with simple logics.
bool isAuth = false;
//check if the user is signed in
#override
void initState() {
super.initState();
googleSignIn.onCurrentUserChanged.listen((account) {
handleSignIn(account);
}, onError: (err) {
print("Error signing in: $err");
});
//maintain the signin
googleSignIn.signInSilently(suppressErrors: false).then((account) {
handleSignIn(account);
}).catchError((err) {
print("Error signing in: $err");
});
}
handleSignIn(GoogleSignInAccount account) {
if (account != null) {
print('User signed in!: $account');
setState(() {
isAuth = true;
});
} else {
setState(() {
isAuth = false;
});
}
}
//sign in using google
login() {
googleSignIn.signIn();
}
logout() {
googleSignIn.signOut();
}
Widget buildAuthScreen() {
return Center(
child: RaisedButton(
child: Text("LogOut"),
onPressed: logout(),
),
);
}
then the unauth screen has basic login layout for signining in...
If you are not doing anything unnecessary in your main, you can just ignore it.
the number of skipped frames is dependent on:
The number of static and top-level variables that need initiation on startup.
Speed of the CPU that will be doing computational work, like parsing JSONs at startup.
Speed of the device storage for initiating databases and shared preferences.
Whether you're using a debug or release build of your app.
The speed of the network connection in case of needing some necessary data before the app starts up.
Whether you're using an emulator or a physical device.
The size of the widget tree in your home page.
This is something you can't control sometimes, I faced this situation where an old android phone showed it skipped 180 frames where as a new phone said it skipped 25.