I have several activities with launchMode SingleInstance. On log out i want to finish all activities and open launchScreen.
val intent = Intent(context, LauncherActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
(context as AppCompatActivity).finishAffinity()
context.startActivity(intent)
However if i press back at Launcher activity i am forwarded to previously launched activities with singleInstance mode
I've tested multiple approach to deal with it such as event propagation, intent flags, counting activity instances, etc. There is some weird scenarios such as starting multiple singleInstance
activities sequentially. In this case, middle activities doesn't start at all (onCreate
method isn't called) and after pressing back button, they'll be started. Therefore no one of the prior approaches works! As the issue is a bit strange, I tried to solve it using a bit strange way.
We maintain the logout state in a singleton object called LogoutHandler
. It cooperates with a class LogoutAwareActivity
which is inherited by all activities except LoginActivity
because it should not be affected by logout mechanism. When the logout occurs, a flag is set in the LogoutHandler
until the last child of LogoutAwareActivity
has finished then clears the flag.
Here is an implementation of that:
LogoutHandler:
import java.util.*
object LogoutHandler {
private var isLogout = false
private var timerWatchDog: TimerWatchDog? = null
fun isLogout() = isLogout
fun onActivityDestroyed() {
if (isLogout) {
timerWatchDog?.refresh(Runnable {
isLogout = false
timerWatchDog = null
})
}
}
fun logout() {
isLogout = true
timerWatchDog = TimerWatchDog(500)
}
private class TimerWatchDog(private val delay: Long) : Runnable {
private var timer: Timer? = null
private var runnable: Runnable? = null
fun refresh(runnable: Runnable) {
this.runnable = runnable
timer?.cancel()
val timerTask = object : TimerTask() {
override fun run() {
Thread(this@TimerWatchDog).start()
}
}
timer = Timer()
timer?.schedule(timerTask, delay)
}
override fun run() {
runnable?.run()
}
}
}
LogoutAwareActivity:
import android.support.v7.app.AppCompatActivity
abstract class LogoutAwareActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
if (LogoutHandler.isLogout()) {
finish()
}
}
override fun onDestroy() {
super.onDestroy()
LoginHandler.onActivityDestroyed()
}
}
A concrete Activity:
class ActivityA : LogoutAwareActivity() {
// ...
}
Another concrete Activity:
class ActivityB : LogoutAwareActivity() {
// ...
}
Your logout function:
fun logout() {
val intent = Intent(context, LoginActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
LogoutHandler.logout()
context.startActivity(intent)
}
Visual Result:
All of MainActivity
, ActivityA
, ActivityB
and ActivityC
are single instance.
Traversing between activities by pressing back button:
Going to LoginActivity
then pressing back button:
Before launching splash screen add this line
ActivityCompat.finishAffinity(this)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With