Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Chronometer, retain time state (and keep counting in background)

I have a timer that counts up from the time a user encounters that activity

I am currently using a Chronometer set during onCreate (initially started only when certain conditions are met). But I need the chronometer to keep counting upward until the app and all its views are closed (I have an "Exit" function to do that).

The problem is that the Chronometer gets reset to zero on every time I look at another tab and come back to its activity. (This has to do with the oncreate, but I dont know the way around it)

I didn't find an intuitive way to save the chronometer's state or countup in the background on its own (or to perhaps keep track of the time on my own and update the chronometer visually at a different point in time)

One idea I had was to start the Chronometer with a service and let the service keep counting , while having a textview in the existing activity update using the chronometer's current time tally as a string

any insight on a known approach to this problem be appreciated!

This is further complicated because this is an activity in a tabhost, and tabhosts call both onPause and onResume every time you load a view, so this breaks lifecycle functions.

like image 648
CQM Avatar asked Oct 07 '11 01:10

CQM


3 Answers

There are a number of ways to persist the time. The easiest one I have found is to store the time in the Intent that was used to create the original activity via getIntent().putExtra("START_TIME", floatvalue). You may retrieve the value with getIntent().getFloatExtra("START_TIME", 0f). Doing it this way has a number of benefits:

  • It doesn't break the Activity LifeCycle and does not require a Context.
  • It can be passed easily between other Activities and Applicaitons.
  • It persists among Pauses and Stops.
  • It doesn't require special listeners.
  • It doesn't create any new objects (the Intent is the one used to create the Activity the first time).

This solution is great for persisting in a Tabbed Activity, or across Dialogs, etc. It has some limitations if leaving the Application to a more memory intensive one, but only if your Activity is destroyed (due to memory).

like image 146
Fuzzical Logic Avatar answered Oct 21 '22 18:10

Fuzzical Logic


Because of my Tabhost, the lifecycle functions could not be relied on.

What I did was make the chronometer a static global in a central class, and added a ontabchangedlistener within my tabhost that checked to see if the tab being changed to was the tab with the chronometer. If this was true then it stores the Long value of the chronometer's current time.

 tabHost.setOnTabChangedListener(new OnTabChangeListener(){

        @Override
        public void onTabChanged(String arg0) {
            // TODO Auto-generated method stub
            if(arg0.contentEquals("homeGroup"))
            {
                //store time in centralhelper.java
                                    //stopWatch is of type Chronometer
                                    //stopWatchLastTime is of type Long and is initially set to zero. Chronometer uses milliseconds to determine time, will never be zero after set
                CentralHelper.stopWatchLastTime = CentralHelper.stopWatch.getBase();
            }
        }

    });

When my homeGroup view loads, the onResume() function is called, there is a condition here to retrieve the time for the chronometer to resume counting from. Despite the fact that a tabhost will call both onPause() and onResume() in EVERY load outside of normal lifecycle functions, they still get called before onCreate()

   public void onResume(){
    super.onResume();

    //update Chronometer with time stored in tabchangelistener
    if(CentralHelper.stopWatchLastTime!=0)
        CentralHelper.stopWatch.setBase(CentralHelper.stopWatchLastTime);
}

this allowed me to do a similar check in onCreate()

    if(CentralHelper.stopWatchLastTime!=0)
    {

        CentralHelper.stopWatch.start(); //this is where it resumes counting from the base set in onResume()
    }
    else
    {
        CentralHelper.stopWatch.start();
        CentralHelper.stopWatch.setBase(SystemClock.elapsedRealtime());
    }
like image 45
CQM Avatar answered Oct 21 '22 19:10

CQM


When you switch to a different activity the previous one is paused (onPause, asand so on, in attached image) when you came back to the activity it is resumed, but occasionaly when dalvik runs out of memory your Activity object can be deleted when ton showing.

If you keep your application data in the Activity instance you might loose it accidentally, please read this Activity Lifecycle http://developer.android.com/reference/android/app/Activity.html

enter image description here

like image 42
michael Avatar answered Oct 21 '22 20:10

michael