How do I create a time-based Flutter App?

5,386

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 GestureDetectors 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.

Share:
5,386
Nick
Author by

Nick

Updated on December 07, 2022

Comments

  • Nick
    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 (
    
        );
    }
    
    }