How do I create a time-based Flutter App?
You can use the Timer class to trigger a log out function after 3 minutes of inactivity. Something you can try is to wrap your entire app in a GestureDetector
that resets the timer on any event. You'd just have to make sure that any other GestureDetector
s in your app use HitTestBehavior.translucent
so the events are propagated to your root listener. Here's a full example:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => AppRoot();
}
class AppRoot extends StatefulWidget {
@override
AppRootState createState() => AppRootState();
}
class AppRootState extends State<AppRoot> {
Timer _timer;
@override
void initState() {
super.initState();
_initializeTimer();
}
void _initializeTimer() {
_timer = Timer.periodic(const Duration(minutes: 3), (_) => _logOutUser);
}
void _logOutUser() {
// Log out the user if they're logged in, then cancel the timer.
// You'll have to make sure to cancel the timer if the user manually logs out
// and to call _initializeTimer once the user logs in
_timer.cancel();
}
// You'll probably want to wrap this function in a debounce
void _handleUserInteraction([_]) {
if (!_timer.isActive) {
// This means the user has been logged out
return;
}
_timer.cancel();
_initializeTimer();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleUserInteraction,
onPanDown: _handleUserInteraction,
onScaleStart: _handleUserInteraction,
// ... repeat this for all gesture events
child: MaterialApp(
// ... from here it's just your normal app,
// Remember that any GestureDetector within your app must have
// HitTestBehavior.translucent
),
);
}
}
UPDATE: I just discovered the Listener class which might make more sense here than the GestureDetector
. I've personally never used it, but feel free to experiment! Check out the documentation on gestures for more info.
Nick
Updated on December 07, 2022Comments
-
Nick 11 months
I need to create a login form. After user successfully login than I need to start some kind of timer (ex: 3 min), so if user has no reaction to app or other word if flutter app state is paused, suspended or inactive more than 3 min. the app will goto main login page. As long as user has interaction with app I need to cancel the timer and only I need to star timer app state is paused, suspended or inactive. How do I do that?
I try to implement the "WidgetsBindingObserver" but its look like is not working as I wanted. If user enters successfully and navigate in app the WidgetsBindingObserver fail (error: state object for widget that no longer appears in the widget tree).
My question is how to implement timed-based flutter app lifecycle, as long as user has interaction with the app? If no user interaction the lifecycle timer will start and if before the timer ends there is a user interaction the timer must be canceled.
class _MyUserHomePageState extends State<MyUserHomePage> with WidgetsBindingObserver { AppLifecycleState _appLifecycleState; @override void initState() { _appStatePasue = false; WidgetsBinding.instance.addObserver(this); super.initState(); } // TODO: DID_CHANGE_APP_LIFE_CYCLE void didChangeAppLifecycleState(AppLifecycleState state) { setState(() { _appLifecycleState = state; if(_appLifecycleState == AppLifecycleState.paused || _appLifecycleState == AppLifecycleState.inactive || _appLifecycleState == AppLifecycleState.suspending) { _appStatePasue = true; print("timer---fired: $_appLifecycleState"); _timer = Timer.periodic(Duration(minutes: 1), _capitalCallback); print(_appLifecycleState); } else { _appStatePasue = false; } }); } // TODO: APP_LIFE_CYCLE__CALLBACK void _capitalCallback(_timer) { if(_appStatePasue == true) { _timer.cancel(); print("return---main---page: $_appLifecycleState"); setState(() { Navigator.push( context, SlideRightRoute(widget: MyApp()) ); }); } else { _timer.cancel(); print("timer---canceled: $_appLifecycleState"); } } @override void dispose() { super.dispose(); } @override void onDeactivate() { super.deactivate(); } @override Widget build(BuildContext context) { return new Scaffold ( ); } }