Skip to content

Instantly share code, notes, and snippets.

@passsy

passsy/KIntent.kt

Last active Sep 29, 2020
Embed
What would you like to do?
Kotlin extension functions to start a generic Activity
package com.pascalwelsch.extensions
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
/**
* Extensions for simpler launching of Activities
*/
inline fun <reified T : Any> Activity.launchActivity(
requestCode: Int = -1,
options: Bundle? = null,
noinline init: Intent.() -> Unit = {}) {
val intent = newIntent<T>(this)
intent.init()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
startActivityForResult(intent, requestCode, options)
} else {
startActivityForResult(intent, requestCode)
}
}
inline fun <reified T : Any> Context.launchActivity(
options: Bundle? = null,
noinline init: Intent.() -> Unit = {}) {
val intent = newIntent<T>(this)
intent.init()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
startActivity(intent, options)
} else {
startActivity(intent)
}
}
inline fun <reified T : Any> newIntent(context: Context): Intent =
Intent(context, T::class.java)
@emoonadev

This comment has been minimized.

Copy link

@emoonadev emoonadev commented Mar 16, 2018

this work: startActivity(Intent(this, AddUserActivity::class.java))
this no work: launchActivity<AddUserActivity> { }

Why not work:

android.content.ActivityNotFoundException: Unable to find explicit activity class {com.emoonadev.gestionclientkotlin/int}; have you declared this activity in your AndroidManifest.xml?
                                                                                       at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1932)
                                                                                       at android.app.Instrumentation.execStartActivity(Instrumentation.java:1615)
                                                                                       at android.app.Activity.startActivityForResult(Activity.java:4472)
                                                                                       at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54)
                                                                                       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:67)
                                                                                       at com.emoonadev.gestionclientkotlin.Activities.MainActivity.onOptionsItemSelected(MainActivity.kt:45)
                                                                                       at android.app.Activity.onMenuItemSelected(Activity.java:3435)
                                                                                       at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:368)
                                                                                       at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
                                                                                       at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:108)
                                                                                       at com.android.tools.profiler.support.event.WindowProfilerCallback.onMenuItemSelected(WindowProfilerCallback.java:133)
                                                                                       at android.support.v7.app.AppCompatDelegateImplV9.onMenuItemSelected(AppCompatDelegateImplV9.java:674)
                                                                                       at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
                                                                                       at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:171)
                                                                                       at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:973)
                                                                                       at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:963)
                                                                                       at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:624)
                                                                                       at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:150)
                                                                                       at android.view.View.performClick(View.java:6256)
                                                                                       at android.view.View$PerformClick.run(View.java:24701)
                                                                                       at android.os.Handler.handleCallback(Handler.java:789)
                                                                                       at android.os.Handler.dispatchMessage(Handler.java:98)
                                                                                       at android.os.Looper.loop(Looper.java:164)
                                                                                       at android.app.ActivityThread.main(ActivityThread.java:6541)
                                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                                       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

My manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.emoonadev.gestionclientkotlin">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Activities.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".Activities.AddUserActivity"
            android:parentActivityName=".Activities.MainActivity" />
        <activity android:name=".Activities.ProductsActivity"></activity>
    </application>

</manifest>
@emoonadev

This comment has been minimized.

Copy link

@emoonadev emoonadev commented Mar 16, 2018

can you send me an example of a project that will use it that I can see why it does not work?
My mail: emoonadev@gmail.com

@samrahimi

This comment has been minimized.

Copy link

@samrahimi samrahimi commented Mar 21, 2018

@emoonadev You have to call the extensions from a Context. Here's a simple example of launching an activity when a button is clicked (using Anko layout and helpers). Assumes there is an Activity class called MapActivity in the project and that you've added the extensions Kotlin to your project (get rid of the top line in the gist with the package name and replace with the package name of your app)

Examples:

class AnkoActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        AnkoActivityUI().setContentView(this)
    }

   fun launchOtherActivity() {
       this.launchActivity<OtherActivity>() 
   }
}

class OtherClass {
    fun launchOtherActivity(ctx: Context) {
       ctx.launchActivity<OtherActivity>() 
   }
}

@hendrawd

This comment has been minimized.

Copy link

@hendrawd hendrawd commented Aug 8, 2018

you can combine with anko's intentFor also, it will be simpler

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Mar 15, 2019

How about fragments? I suggest slightly improve this functions:

inline fun <reified T : Any> Activity.launchActivity(
    requestCode: Int = -1,
    options: Bundle? = null,
    noinline init: Intent.() -> Unit = {}) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
          startActivityForResult(newIntent<T>(this, init), requestCode, options)
    else
         startActivityForResult(newIntent<T>(this, init), requestCode)
}

inline fun <reified T : Any> Context.launchActivity(
    options: Bundle? = null,
    noinline init: Intent.() -> Unit = {}) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
          startActivity(newIntent<T>(this, init), options)
    else
         startActivity(newIntent<T>(this, init))
}

@RequiresApi(Build.VERSION_CODES.HONEYCOMB)
inline fun <reified T : Any> Fragment.launchActivity(
    requestCode: Int = -1,
    options: Bundle? = null,
    noinline init: Intent.() -> Unit = {}) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
          startActivityForResult(newIntent<T>(requireContext(), init), requestCode, options)
    else
         startActivityForResult(newIntent<T>(requireContext(), init), requestCode)
}

inline fun <reified T : Any> newIntent(context: Context, noinline init: Intent.() -> Unit = {}): Intent {
    val intent = Intent(context, T::class.java)
    intent.init()
    return  intent
}
@denebchorny

This comment has been minimized.

Copy link

@denebchorny denebchorny commented Jul 20, 2020

Why do you use startActivityForResult instead of startActivity?

IDK, but would it be good to be able to choose which one to use?

For example, one fun launchActivity and another one fun launchActivityForResult.

What do you think? Or is it right to use alwaysstartActivityForResult?

@passsy

This comment has been minimized.

Copy link
Owner Author

@passsy passsy commented Jul 20, 2020

I use both. If you provide a requestCode it calls startActivityForResult otherwise startActivity

@denebchorny

This comment has been minimized.

Copy link

@denebchorny denebchorny commented Jul 20, 2020

Yep, I did research, and it's funny what I found. StartActivity calls startActivityForResult internally; then, it means that we would say its the same.

public void startActivity(Intent intent, @nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}

@passsy

This comment has been minimized.

Copy link
Owner Author

@passsy passsy commented Jul 20, 2020

It's important to call the correct method though. startActivity might be overridden or - unlikely - the internal implementation might change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment