Not sure if I can answer all your questions but here's my two cents:
Your code looked like this when your app crashed:
btn_scan.setOnClickListener {
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
applicationContext.startActivity(mIntent)
}
The error message said you should use FLAG_ACTIVITY_NEW_TASK when starting an Activity from outside of an Activity context. You used the Application context which is like a "cousin" of the Activity context inheritance-wise (see ContextWrapper for subclasses and their relations), so the Intent flags were checked and the required flag was missing.
But why can the flag be missing if you set it explicitly?
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
That's because you assign another value to mIntent.flags immediately after this:
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
If you want to have both flags you have to add them:
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_CLEAR_TOP
Now the app no longer crashes.
But is the Application context even necessary here? Your code is part of an Activity after all, and Activity is an indirect subclass of Context.
You possibly tried the following and it worked:
btn_scan.setOnClickListener {// Note: your IDE tells you "it: View!"
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
this.startActivity(mIntent)
}
Because inside the OnClickListener lambda, the View is referred to by "it", there is no ambiguity: "this" refers to the Activity, no crash.
(Of course now you could skip the Intent.FLAG_ACTIVITY_NEW_TASK)
Things look differently when you have something like this:
with(btn_scan){ // this: Button!
setOnClickListener{ // it: View!
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_CLEAR_TOP
this.startActivity(mIntent)
}
}
Now your IDE won't accept this.startActivity(mIntent). This is because here "this" refers to the Button. If you want another, "outer this", you have to say explicitly which one. In Kotlin, you do so by adding @ActivityName.
I suppose the same goes for coroutine code inside an Activity (although I must confess I'm not yet a coroutine expert): whenever the Activity "this" is hidden behind some local "this", you need the annotation.
Back to familiar ground: the context property of a Fragment is the Activity's context if the Fragment is attached to an Activity, else it is null. So if it's not null you can use it for starting an Activity.
But you can even use the Button's context property, since it is identical to the Activity context as well:
with(btn_scan){ // this: Button!
setOnClickListener{
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
this.context.startActivity(mIntent)
}
}