Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect user inactivity in Flutter

I developed my app for Android using Java and now want to migrate to Flutter.

For detecting user inactivity I override this method in my Activity: onUserInteraction and reset a Timer, if there is no user interaction, I show a Screen Saver like Animation.

Is there Any clean way in Flutter to do this? I don't want to use platform channels. I want it pure Dart and flutter. I know I can set timer and reset it on user touch, but like in Android I want system to inform me about the user interaction.

like image 308
Mneckoee Avatar asked Oct 21 '25 06:10

Mneckoee


2 Answers

You can use wrap your MaterialApp in Listener. And reset a timer on interaction. Similar to what you are doing in android.

It only listens for gestures such as tap, drag, then released or canceled. It does not however listen to mouse events like hovering a region without pressing any buttons. For such events, use MouseRegion.

Sample code:

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: (_) => print('down'), // best place to reset timer imo
      onPointerMove: (_) => print('move'),
      onPointerUp: (_) => print('up'),
      child: MaterialApp(
        theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          body: Center(
            child: MyWidget(),
          ),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return TextFormField(
      maxLength: 10,
      maxLengthEnforced: true,
      decoration: InputDecoration(
        border: OutlineInputBorder(),
        labelText: 'Details',
      ),
    );
  }
}
like image 193
Vineet Avatar answered Oct 25 '25 02:10

Vineet


I have a similar logic behind my app and here is what i came up with.

class _MyHomePageState extends State<MyHomePage> {
InActivityTimer timer = InActivityTimer();
int _counter = 0;

void _incrementCounter() {
timer.handleUserInteraction(context);
setState(() {
  _counter++;
});
}

@override
void initState() {
// TODO: implement initState
super.initState();
timer.startTimer(context);
}

@override
Widget build(BuildContext context) {
return Listener(
  onPointerHover: (_) {
    timer.handleUserInteraction(context);
  },
  onPointerMove: (_) {
    timer.handleUserInteraction(context);
  },
  child: RawKeyboardListener(
  focusNode: FocusNode(),
  onKey: (RawKeyEvent event) {
    if (event is RawKeyDownEvent) {
      timer.handleUserInteraction(context);
      }
  child: Scaffold(
    appBar: AppBar(
      backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      title: Text(widget.title),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          const Text(
            'You have pushed the button this many times:',
          ),
          Text(
            '$_counter',
            style: Theme.of(context).textTheme.headlineMedium,
          ),
        ],
      ),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: _incrementCounter,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ), 
    ),
    );
    }
    }

    class InActivityTimer {
    Timer? _timer;
    DateTime? lastInteractionTime;

    void startTimer(BuildContext context) {
     lastInteractionTime = DateTime.now();
    _startInactivityTimer(context);
  }

  void _startInactivityTimer(BuildContext context) {
    print("start Inactivity timer is triggered");
    if (_timer != null && _timer!.isActive) {
      _timer!.cancel();
    }

    _timer = Timer(Duration(seconds: 10), () {
      _restartApp(context);
    });
  }

  void _restartApp(BuildContext context) {
    print("restarting the app");
    // You can use platform-specific code to restart the app here.
    // This example uses Flutter's `runApp` to restart the app.
    RestartWidget.restartApp(context);
  }

  void handleUserInteraction(BuildContext context) {
    print("Handling user interaction");
    lastInteractionTime = DateTime.now();
    _startInactivityTimer(context);
  }
}
}
like image 27
Biloliddin Makhmudov Avatar answered Oct 25 '25 03:10

Biloliddin Makhmudov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!