简体   繁体   中英

android stopwatch stops working when screen is off

Hi I recently have made a simple stopwatch app, it work fine. However when I switch the screen of and turn it back on the timer shows the last value of time. For example if the timer was showing me 00:00:10 , turn the screen of (for 5s) turn it back on it and it will show same value and the starts to increase the time value.

Any suggestion why ?

Thanks

      if (savedInstanceState != null) {
        seconds = savedInstanceState.getInt("seconds");
        running = savedInstanceState.getBoolean("running");
        wasRunning = savedInstanceState.getBoolean("wasRunning");
    }

    runTimer();
}


public void onClickStart(View view){
    running = true;
}

public void onClickStop(View view){
    running = false;
}

public void onClickReset(View view){
    running = false;
    seconds = 0;
}


@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putInt("seconds", seconds);
    savedInstanceState.putBoolean("running", running);
    savedInstanceState.putBoolean("wasRunning",wasRunning);
}


@Override
protected void onPause(){
    super.onPause();
    wasRunning = running;
    running = false;
}

@Override
protected void onResume(){
    super.onResume();
    if(wasRunning){
        running = true;
    }
}

@Override
protected void onStop(){
    super.onStop();
    wasRunning = running;
    running = false;
}

@Override
protected void onStart(){
    super.onStart();
    if(wasRunning){
        running = true;
    }
}

private void runTimer(){
    final TextView timeView = (TextView)findViewById(R.id.time_view);
    final Handler handler = new Handler();

    handler.post(new Runnable() {
        @Override
        public void run() {

            int hours = seconds/3600;
            int minutes = (seconds%3600)/60;
            int secs = seconds%60;

            String time = String.format("%d:%02d:%02d",hours,minutes,secs);
            timeView.setText(time);

            if(running){
                seconds++;
            }
            handler.postDelayed(this,1000);
        }
    });

}
@Override
protected void onPause(){
    super.onPause();
    wasRunning = running;
    running = false;
}

@Override
protected void onResume(){
    super.onResume();
    if(wasRunning){
        running = true;
    }
}

@Override
protected void onStop(){
    super.onStop();
    wasRunning = running;
    running = false;
}

@Override
protected void onStart(){
    super.onStart();
    if(wasRunning){
        running = true;
    }
}

Just look into your code, you are changing the value of running to false whenever your activity Pauses or Stops . And look into the Timer, it only increases the value if running is true .

The stopwatch should be created within a service that runs in the background. Your activity should only read and present the time out of the service logic.

Right now your stopwatch is bindend to the activity lifecycle thread and because of it the time count is stopped while your activity / app is in the background.

See here a right implementation example.

尝试在清单中添加此权限

<uses-permission android:name="android.permission.WAKE_LOCK" />

To ensure both clock consistency (your problem - show the real time since start) and clock accuracy (avoid small cumulative errors) you just have to measure the time elapsed from your start time:

// first get the time in miliseconds
long start = System.currentTimeMillis();

Then in your timer measure the difference:

// every now and then, get the current time and substract
long now = System.currentTimeMillis();
seconds = (now - start) / 1000;

As your activity could be destroyed and session data dropped, you should save and restore your start time in SharedPreferences. You do not need a Service as others suggested.

@Override
protected void onCreate(Bundle state){
   super.onCreate(state);
   . . .

   // Restore preferences
   SharedPreferences settings = getSharedPreferences();
   start = settings.getLong("start_time", 0);
   if (start != 0) {
       running = true;
   }
}

 @Override
 protected void onStop(){
 super.onStop();
 if (running) {
     SharedPreferences settings = getSharedPreferences();
     SharedPreferences.Editor editor = settings.edit();
     editor.putLong("start_time", startTime);
     editor.apply();
 }

You could be tempted to save these values in onSaveInstanceState() Bundle - but this will be destroyed by the System if you don't use the app for a long time. The SharedPreferences are persistent allowing you to measure any long period of time.

Obviously you need to refresh the saved startTime when you start / stop the stop watch. You can also save the boolean and this would allow you to keep the startTime and endTime or timeElapsed; there are many ways you can implement this but the basic ideea is always measure the time difference between start time and now (or stop time).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM