Kotlin extension function start activity with Intent extras
Asked Answered
K

7

14

I am trying to write a kotlin extension function for Context which will start a new activity in android with given class name and list of intent extras. I am able to successfully start activity without any extras but I am facing problem with them.

fun <T> Context.openActivity(it: Class<T>, pairs: List<Pair<String, Any>>) {
  var intent = Intent()
  pairs.forEach {
     intent.putExtra(it.first, it.second)
  }
  startActivity(intent)
}

Main issue here is -> intent.putExtra() doesn't except second param as Any

Koster answered 16/12, 2018 at 15:32 Comment(0)
J
26

Instead of using a list of pairs, consider using a Bundle. Then you can add it with putExtras(Bundle).

If you want to go one step ahead, you could add a lambda extension to configure the extras:

fun <T> Context.openActivity(it: Class<T>, extras: Bundle.() -> Unit = {}) {
  val intent = Intent(this, it)
  intent.putExtras(Bundle().apply(extras))
  startActivity(intent)
}

Then you can call it as:

openActivity(MyActivity::class.java) {
  putString("string.key", "string.value")
  putInt("string.key", 43)
  ...
}
Jalapa answered 16/12, 2018 at 15:46 Comment(4)
Thanks for this brilliant lambda extension approach. Can you please redirect me to a site where I can read more about this as a want to understand the concept of this extension approach. Thanks in advance.Koster
intent.addExtras(Bundle().apply(extras)) 1)This doesn't exist 2) If I want to add flag in intent how?Uhland
@Subho 1 was a spelling issue. The text was more exact about it. For 2 you'd have to implement openActivity to also set the flag to the intent or use a closure with Intent as a receiver instead.Jalapa
Are you referring to my answer? @JalapaUhland
D
19

Declare:

inline fun <reified T : Activity> Context.startActivity(block: Intent.() -> Unit = {}) {
    startActivity(Intent(this, T::class.java).apply(block))
}

Simple using:

startActivity<MainActivity>()

With extra

startActivity<MainActivity>{
   putExtra("param 1", "Simple")
}
Diadromous answered 13/9, 2019 at 14:27 Comment(5)
additionally, instead of block(intent) you can also call intent.block() or Intent(this, T::class.java).apply(block)Buchalter
@SubaruTashiro Can you please show entire code for what you suggest? It seems nicer.Licha
inline fun <reified T : Activity> Context.startActivity(block: Intent.() -> Unit = {}) { startActivity(Intent(this, T::class.java).apply(block)) }Saran
Thanks to Subaru Tashiro, Crypher. I just edited my answer.Diadromous
Amazing way of writing an ext classArrowy
C
3

Here is the extension function for start activity:

inline fun <reified T : Activity> Context.openActivity(vararg params: Pair<String, Any>) {
    val intent = Intent(this, T::class.java)
    intent.putExtras(*params)
    this.startActivity(intent)
}

fun Intent.putExtras(vararg params: Pair<String, Any>): Intent {
    if (params.isEmpty()) return this
    params.forEach { (key, value) ->
        when (value) {
            is Int -> putExtra(key, value)
            is Byte -> putExtra(key, value)
            is Char -> putExtra(key, value)
            is Long -> putExtra(key, value)
            is Float -> putExtra(key, value)
            is Short -> putExtra(key, value)
            is Double -> putExtra(key, value)
            is Boolean -> putExtra(key, value)
            is Bundle -> putExtra(key, value)
            is String -> putExtra(key, value)
            is IntArray -> putExtra(key, value)
            is ByteArray -> putExtra(key, value)
            is CharArray -> putExtra(key, value)
            is LongArray -> putExtra(key, value)
            is FloatArray -> putExtra(key, value)
            is Parcelable -> putExtra(key, value)
            is ShortArray -> putExtra(key, value)
            is DoubleArray -> putExtra(key, value)
            is BooleanArray -> putExtra(key, value)
            is CharSequence -> putExtra(key, value)
            is Array<*> -> {
                when {
                    value.isArrayOf<String>() ->
                        putExtra(key, value as Array<String?>)
                    value.isArrayOf<Parcelable>() ->
                        putExtra(key, value as Array<Parcelable?>)
                    value.isArrayOf<CharSequence>() ->
                        putExtra(key, value as Array<CharSequence?>)
                    else -> putExtra(key, value)
                }
            }
            is Serializable -> putExtra(key, value)
        }
    }
    return this
}

Simple using:

openActivity<TestActivity>("key0" to "value0", "key1" to "value1")

A simpler approach is provided in Kotlin

Use the bundleOf()

inline fun <reified T : Activity> Context.openActivity1(vararg params: Pair<String, Any?>) {
    val intent = Intent(this, T::class.java)
    intent.putExtras(bundleOf(*params))
    this.startActivity(intent)
}

Chud answered 4/1, 2021 at 2:50 Comment(2)
Hi you can use bundleOf() in Kotlin for passing params in android KotlinAscites
@NafisKabbo I just discovered this method. It's very convenient. Thank youChud
U
2

Here is the extension function for start activity:

inline fun <reified T : Activity> Context.openActivity(noinline extra: Intent.() -> Unit) {
      val intent = Intent(this, T::class.java)
      intent.extra()
      startActivity(intent)
}

You can call this function like this way:

openActivity<MyActivity> {
    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    putExtra(LaBoxConstants.DEFAULT_LANDING, Default_Landing)
    putExtra(HomeActivity.APP_RELAUNCH, AppReLaunched)
}

NOTE: IT IS NOT A RECOMMENDED WAY TO START ACTIVITY. USE STARTACTIVITY INSTEAD.

Uhland answered 3/9, 2019 at 11:41 Comment(1)
why is this not a recommended way to start activity? it seems pretty convenient to meBuchalter
M
2

I personally prefer an approach where I have a method that defines the flag for an activity, to prevent having to re-write the flags for every startActivity invocation.

internal inline fun <reified T: Activity> Context.startActivity(activity: KClass<T>, noinline modifyIntent: Intent.() -> Unit) {
    val intent = Intent(this, activity.java)
        .addFlags(flagsForActivity(activity))
        .modifyIntent()

    startActivity(intent)
}

private fun <T: Activity> flagsForActivity(activity: KClass<T>): Int {
    return when (activity) {
        LoginActivity::class -> Intent.SPECIFIC_FLAGS
        else -> Intent.DEFAULT_FLAGS
    }
}

And then the way it would be called is

startActivity(LoginActivity::class) {
    putExtra("Username", "username")
}
Madera answered 14/12, 2021 at 10:4 Comment(0)
H
1

There is no method putExtra(String, Any) in the Intent object. You can use Bundle object to save your data:

fun <T> Context.openActivity(it: Class<T>, bundleKey: String, bundle: Bundle) {
    var intent = Intent(this, it)
    intent.putExtra(bundleKey, bundle)
    startActivity(intent)
}

To call it inside Context object:

val bundle = Bundle()
bundle.putString("Key", "Value") // you can put another object here
openActivity(SomeActivity::class.java, "Bundle Key", bundle)
Hiss answered 16/12, 2018 at 15:43 Comment(0)
G
0
private inline fun <reified T : Any> Context.startActivity() {
    val intent = Intent(this, T::class.java)
    startActivity(intent)
    finish()
}

pass activity using

startActivity<MainActivity2>()

Germainegerman answered 29/3 at 9:14 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Cinerary

© 2022 - 2024 — McMap. All rights reserved.