1

https://codinginflow.com/tutorials/android/countdowntimer/part-3-run-in-background

I am watching this tutorial, i want to change some things : I want to display a message "Time Out" after 6 seconds, by using CountDownTimer. It works when i am in TimerActivity, but when i go to another activity (such as WelcomeActivity), then the application do not display the message. How to achieve the message "Time Out" in the WelcomeActivity ?

enter image description here

enter image description here

TimerActivity

class TimerActivity : AppCompatActivity() {
    companion object {
        var START_TIME_IN_MILLIS : Long = 6000
    }
    private var mTextViewCountDown: TextView? = null
    private var mButtonStartPause: Button? = null
    private var mButtonReset: Button? = null
    private var mCountDownTimer: CountDownTimer? = null
    private var mTimerRunning: Boolean = false
    private var mTimeLeftInMillis : Long =0

private var mEndTime : Long = 0

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_timer)
    mTextViewCountDown = findViewById(R.id.text_view_countdown)
    mButtonStartPause = findViewById(R.id.button_start_pause)
    mButtonReset = findViewById(R.id.button_reset)
    btnWelcomeAct.setOnClickListener {
        val intent = Intent(this@TimerActivity, Welcome::class.java)
        startActivity(intent)

    }

    mButtonStartPause!!.setOnClickListener {
        if (mTimerRunning) {
            pauseTimer()
        } else {
            startTimer()
        }

    }

    mButtonReset!!.setOnClickListener {
        resetTimer()
    }
    updateCountDownText()
}

private fun startTimer() {
    mEndTime = System.currentTimeMillis() + mTimeLeftInMillis

    mCountDownTimer = object : CountDownTimer(mTimeLeftInMillis, 1000) {
        override fun onTick(millisUntilFinished: Long) {
            mTimeLeftInMillis = millisUntilFinished
            updateCountDownText()
        }

        override fun onFinish() {
            mTimerRunning = false
            updateButton()
            Toast.makeText(applicationContext,"Time out", Toast.LENGTH_SHORT).show()
        }
    }.start()
    mTimerRunning = true
    updateButton()
}


private fun pauseTimer() {
    mCountDownTimer!!.cancel()
    mTimerRunning = false
    updateButton()
}

private fun resetTimer() {
    mTimeLeftInMillis = START_TIME_IN_MILLIS
    updateCountDownText()
    updateButton()
}


private fun updateCountDownText() {
    val minutes = mTimeLeftInMillis / 1000 / 60
    val seconds = mTimeLeftInMillis / 1000 % 60
    val timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds)
    mTextViewCountDown!!.text = (timeLeftFormatted)

}

private fun updateButton() {
    if (mTimerRunning) {
        mButtonReset!!.setVisibility(View.INVISIBLE)
        mButtonStartPause!!.setText("Pause")
    } else {
        mButtonStartPause!!.setText("Start")
        if (mTimeLeftInMillis < 1000) {
            mButtonStartPause!!.setVisibility(View.INVISIBLE)
        } else {
            mButtonStartPause!!.setVisibility(View.VISIBLE)
        }
        if (mTimeLeftInMillis < START_TIME_IN_MILLIS) {
            mButtonReset!!.setVisibility(View.VISIBLE)
        } else {
            mButtonReset!!.setVisibility(View.INVISIBLE)
        }
    }
}

override fun onStop() {
    super.onStop()
    val prefs = getSharedPreferences("prefs", Context.MODE_PRIVATE)
    val editor = prefs.edit()
    editor.putLong("millisLeft", mTimeLeftInMillis)
    editor.putBoolean("timerRunning", mTimerRunning)
    editor.putLong("endTime", mEndTime)
    editor.apply()
    if (mCountDownTimer != null) {
        mCountDownTimer!!.cancel()
    }
}

override fun onStart() {
    super.onStart()
    val prefs = getSharedPreferences("prefs", Context.MODE_PRIVATE)
    mTimeLeftInMillis = prefs.getLong("millisLeft", START_TIME_IN_MILLIS)
    mTimerRunning = prefs.getBoolean("timerRunning", false)
    updateCountDownText()
    updateButton()
    if (mTimerRunning) {
        mEndTime = prefs.getLong("endTime", 0)
        mTimeLeftInMillis = (mEndTime - System.currentTimeMillis())
        if (mTimeLeftInMillis < 0) {
            mTimeLeftInMillis = 0
            mTimerRunning = false
            updateCountDownText()
            updateButton()
        } else {
            startTimer()
        }
    }
}

override fun onBackPressed() {
    val intent = Intent(this@TimerActivity, Welcome::class.java)
    startActivity(intent)
}
}

Class WelcomeActivity

How to display the message "Time Out" in this activiy when CountDownTimer in TimerActivity finished?

class Welcome : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_welcome)
}
John
  • 78
  • 1
  • 9
  • 1
    In your TimerActivity, your `CountDownTimer` will stop when `onStop` called, the situation relies on activity's life-cycle changed. So you can try remove the `mCountDownTimer!!.cancel()` to achieve it. – Hababa Jun 18 '20 at 04:54
  • I remove mCountDownTimer!!.cancel(), it works (display the message). Now, i want to close the app after 6 seconds, i added finishAffinity(), but it won't close the app after 6 seconds. – John Jun 18 '20 at 06:15
  • In the case you can refer to [here](https://stackoverflow.com/a/51848705/9629748) – Hababa Jun 18 '20 at 07:44

1 Answers1

1

There are so many way to update UI after switching another activity. I'm sharing some of way which may help you in updating UI from another activity:

1) Event Bus

2) Broadcast receiver

3) In case you use MVVM architecture, then you can create custom viewModel which is alive with application alive.

Event Bus

you need to add EventBus dependency

1) compile 'de.greenrobot:eventbus:2.4.0'

2) create a pojo

public class DataSyncEvent {
    private final String syncStatusMessage;
    public DataSyncEvent(String syncStatusMessage) {
        this.syncStatusMessage = syncStatusMessage;
    }
    public String getSyncStatusMessage() {
        return syncStatusMessage;
    }
}

3) call from your countdowntimer

EventBus.getDefault().post(new DataSyncEvent("Sync SuccessFully”);

4) Subscribe in activity which you want to get update

@Subscribe
public void onEvent(DataSyncEvent syncStatusMessage)
{
    Toast.makeText(this, syncStatusMessage.getSyncStatusMessage(), Toast.LENGTH_SHORT).show();
}

Note: Don't forgot register and unregister

@Override
protected void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    EventBus.getDefault().unregister(this);
}

Broadcast receiver:

1) call from countdowntimer

MyReceiver receiver = new MyReceiver(new Handler()); // Create the receiver
registerReceiver(receiver, new IntentFilter("some.action")); // Register receiver

sendBroadcast(new Intent("some.action"));

2) In another activity:

public static class MyReceiver extends BroadcastReceiver {

        private final Handler handler; // Handler used to execute code on the UI thread

        public MyReceiver(Handler handler) {
            this.handler = handler;
        }

        @Override
        public void onReceive(final Context context, Intent intent) {
            // Post the UI updating code to our Handler
            handler.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(context, "Toast from broadcast receiver", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }   

Thanks

webaddicted
  • 1,071
  • 10
  • 23
  • Thanks for you help, i remove mCountDownTimer!!.cancel(), it works. Now, i want to close the app after 6 seconds instead of display message, how to do this? Use the broadcast receiver? – John Jun 18 '20 at 06:17
  • You can close your app by using **finishAffinity()** that will finish the current activity and all parent activities. But it work fron android 4.1 or higher. **For Api 16± use finishAffinity()** for lower 4.1, use. **ActivityCompat.finishAffinity(yourActivity.this)** – webaddicted Jun 18 '20 at 06:32
  • If i stayed at TimerActivity, app will be closed.But, if i am in WelcomeActivity, app won't close. Do you have any suggestion? – John Jun 18 '20 at 06:40
  • You can check ur timer activity is in active state or not, by keeping a boolean global variable in activity whose value change in onresume or in onstop – webaddicted Jun 18 '20 at 06:51