3

I have developed and app and the client want me to store the total time spend by the user inside the app how can I achieve that I have tried using this App_usage package in flutter but its showing me Star Activity error if you guys have any solution
please let me know thanks in advance :)

Madan Raj
  • 43
  • 2
  • 4
  • 1
    I think you could do this by running a timer in the background. You could start the timer in initState. I also suggest learning state management: https://flutter.dev/docs/development/data-and-backend/state-mgmt/options . You might have to use it while implementing the feature you want. – CoderUni Oct 07 '20 at 14:28

3 Answers3

2

Have some variable that tracks the start time and end/ pause time of the app and persist the difference. You will have to hook that up to the app lifecycle to listen to events such as pausing/ resuming the app. (e.g. How to handle onPause/onResume in Flutter App?)

Something like this:

class AppLifecycleReactor extends StatefulWidget {
  const AppLifecycleReactor({Key key}) : super(key: key);

  @override
  _AppLifecycleReactorState createState() => _AppLifecycleReactorState();
}

class _AppLifecycleReactorState extends State<AppLifecycleReactor>
    with WidgetsBindingObserver {
  DateTime startTime;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      startTime = DateTime.now();
    }

    if (state == AppLifecycleState.detached ||
        state == AppLifecycleState.paused) {
      var usageTime = DateTime.now().difference(startTime);
      // do whatever with the usageTime
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: MyContent(),
    );
  }
}
Chris Marx
  • 66
  • 5
  • hey thanks , but i don't this will work because see the resume and pause is the middle process of the app how i want is when user enters the app the timer should start and when the app gets closed [not paused] then the timer should stop and save the recent value so for that do you have any suggestion or plan or anything would be great help – Madan Raj Oct 09 '20 at 16:39
  • You can use only AppLifecycleState.detached but you have to handle the setting of the startTime differently, because AppLifecycleState.resumed will be triggered by either starting or resuming the app. You could just out it in your roots widgets init method. – Chris Marx Oct 10 '20 at 11:17
  • hey brother thanks for the help, after this i am facing new problem that is when the app is detach or inactive state it cannot make api calls , is that cannot be done or can it be done thanks in advance :) – Madan Raj Oct 10 '20 at 18:40
  • Future updateTimer() async { making http call ... } override Future didChangeAppLifecycleState(AppLifecycleState state) async { SharedPreferences prefs = await SharedPreferences.getInstance(); if (state.toString() == "AppLifecycleState.detached") { var _hours, _minutes; _hours = prefs.getInt("hours"); _minutes = var ttoken =.., ;var uuserId =..; // this function is beeing called but api call is not beeing executed await updateTimer(_hours, _minutes, ttoken, uuserId); print(ye); } } – Madan Raj Oct 12 '20 at 04:36
  • I'm more or less guessing now, but I would say that you can't make a asynchronous call when the app is going to be detached/ inactive since the call might take longer and the app will, as stated, be inactive and unable to respond. You could try to handle that in the on resume method instead. Also some tipps: 1. You don't need `state.toString() == "AppLifecycleState.detached"` `state == AppLifecycleState.detached` works and 2. You should rather keep the time as a single number in milliseconds or seconds (unix time) instead of saving hours and minutes separately. – Chris Marx Oct 12 '20 at 08:15
0

like Chris Marx said, you can use the counter to store usage time. and to handle the sync operation to server, you can use shared preferenceq to store data and when the app launched again you do sync(update) with the server.

  • Your answer is more like a comment that could have been added to the answer that you liked. – JohnH Oct 09 '21 at 01:10
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/30025756) – Axisnix Oct 09 '21 at 08:46
0
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(new HomePage());
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String? docId;

  addTime() async {
    docId = await TimeHomePageUsage.addUserStartTime();
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    addTime();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    TimeHomePageUsage.addUserEndTime(docId);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text('Home Page'),
      ),
    );
  }
}

class TimeHomePageUsage {
  static Future<String?> addUserStartTime() async {
    String? docId;
    await FirebaseFirestore.instance
        .collection('timeUsage')
        .add({'startTime': DateTime.now().toString()})
        .then((doc) => print("Start Time added ${docId = doc.id} "))
        .catchError((error) => print("Failed to add Start Time: $error"));
    return docId;
  }

  static Future<void> addUserEndTime(String? docId) async {
    await FirebaseFirestore.instance
        .collection('timeUsage')
        .doc(docId)
        .update({"endTime": DateTime.now().toString()})
        .then((value) => print("End Time added "))
        .catchError((error) => print("Failed to add End Time: $error"));
  }
}
  • Home Page is a statefull widget when User Open the app then this page initiated and addUserStartTime() is called which add User start time on firebaseFirestore, when user leave home page then dispose() method call the addUserEndTime() which add end Time. – Saboor Khan Apr 09 '22 at 06:11
  • this app manage a database of start and end time when ever user open your app day / night. you can add this functionality on any page which record your mostly visited page – Saboor Khan Apr 09 '22 at 06:22
  • here you can get usage of your app by users according to hour/day/night/date/month/year – Saboor Khan Apr 09 '22 at 06:36