diff --git a/api/current.txt b/api/current.txt
index e805fde9..cc3fa878 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1,3 +1,11 @@
+package androidx.core.activity {
+
+ public final class ActivityKt {
+ ctor public ActivityKt();
+ }
+
+}
+
package androidx.core.animation {
public final class AnimatorKt {
diff --git a/src/androidTest/AndroidManifest.xml b/src/androidTest/AndroidManifest.xml
index 6f5cb7ec..907fe7fd 100644
--- a/src/androidTest/AndroidManifest.xml
+++ b/src/androidTest/AndroidManifest.xml
@@ -3,5 +3,6 @@
+
diff --git a/src/androidTest/java/androidx/core/TextExtraActivity.kt b/src/androidTest/java/androidx/core/TextExtraActivity.kt
new file mode 100644
index 00000000..8231790d
--- /dev/null
+++ b/src/androidTest/java/androidx/core/TextExtraActivity.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core
+
+import android.app.Activity
+import androidx.core.activity.extra
+
+class TextExtraActivity : Activity() {
+
+ val stringExtra by extra(EXTRA_STRING)
+ val intExtra by extra(EXTRA_INT)
+ val nullableIntExtra by extra(EXTRA_NULLABLE_INT)
+ val intDefaultExtra by extra(EXTRA_INT_DEFAULT) { DEFAULT_INT }
+ val nullableIntDefaultExtra by extra(EXTRA_NULLABLE_INT_DEFAULT) { DEFAULT_NULLABLE_INT }
+
+ companion object {
+ const val EXTRA_STRING = "string"
+ const val EXTRA_INT = "int"
+ const val EXTRA_NULLABLE_INT = "nullable_int"
+ const val EXTRA_INT_DEFAULT = "int_default"
+ const val EXTRA_NULLABLE_INT_DEFAULT = "nullable_int_default"
+
+ const val DEFAULT_INT: Int = 42
+ val DEFAULT_NULLABLE_INT: Int? = null
+ }
+}
\ No newline at end of file
diff --git a/src/androidTest/java/androidx/core/activity/ActivityTest.kt b/src/androidTest/java/androidx/core/activity/ActivityTest.kt
new file mode 100644
index 00000000..77906c8e
--- /dev/null
+++ b/src/androidTest/java/androidx/core/activity/ActivityTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.activity
+
+import android.content.Intent
+import android.os.Bundle
+import android.support.test.rule.ActivityTestRule
+import androidx.core.TextExtraActivity
+import androidx.testutils.assertThrows
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Rule
+import org.junit.Test
+
+class ActivityTest {
+
+ @JvmField
+ @Rule
+ val rule = ActivityTestRule(TextExtraActivity::class.java, false, false)
+
+ @Test
+ fun get() {
+ val activity = launchExtraActivity {
+ putExtra(TextExtraActivity.EXTRA_STRING, "test")
+ putExtra(TextExtraActivity.EXTRA_INT, 1)
+ putExtra(TextExtraActivity.EXTRA_NULLABLE_INT, 2)
+ putExtra(TextExtraActivity.EXTRA_INT_DEFAULT, 3)
+ putExtra(TextExtraActivity.EXTRA_NULLABLE_INT_DEFAULT, 4)
+ }
+ assertEquals("test", activity.stringExtra)
+ assertEquals(1, activity.intExtra)
+ assertEquals(2, activity.nullableIntExtra)
+ assertEquals(3, activity.intDefaultExtra)
+ assertEquals(4, activity.nullableIntDefaultExtra)
+ }
+
+ @Test
+ fun getMissing() {
+ val activity = launchExtraActivity()
+ assertThrows { activity.stringExtra }
+ assertThrows { activity.intExtra }
+ assertNull(activity.nullableIntExtra)
+ assertEquals(TextExtraActivity.DEFAULT_INT, activity.intDefaultExtra)
+ assertEquals(TextExtraActivity.DEFAULT_NULLABLE_INT, activity.nullableIntDefaultExtra)
+ }
+
+ @Test
+ fun getNull() {
+ val activity = launchExtraActivity {
+ putExtra(TextExtraActivity.EXTRA_STRING, null as String?)
+ putExtra(TextExtraActivity.EXTRA_INT, null as Int?)
+ putExtra(TextExtraActivity.EXTRA_NULLABLE_INT, null as Int?)
+ putExtra(TextExtraActivity.EXTRA_INT_DEFAULT, null as Int?)
+ putExtra(TextExtraActivity.EXTRA_NULLABLE_INT_DEFAULT, null as Int?)
+ }
+ assertThrows { activity.stringExtra }
+ assertThrows { activity.intExtra }
+ assertNull(activity.nullableIntExtra)
+ assertEquals(TextExtraActivity.DEFAULT_INT, activity.intDefaultExtra)
+ assertEquals(TextExtraActivity.DEFAULT_NULLABLE_INT, activity.nullableIntDefaultExtra)
+ }
+
+ @Test
+ fun getWrongType() {
+ val activity = launchExtraActivity {
+ putExtra(TextExtraActivity.EXTRA_STRING, Bundle())
+ putExtra(TextExtraActivity.EXTRA_INT, Bundle())
+ putExtra(TextExtraActivity.EXTRA_NULLABLE_INT, Bundle())
+ putExtra(TextExtraActivity.EXTRA_INT_DEFAULT, Bundle())
+ putExtra(TextExtraActivity.EXTRA_NULLABLE_INT_DEFAULT, Bundle())
+ }
+ assertThrows { activity.stringExtra }
+ assertThrows { activity.intExtra }
+ assertThrows { activity.nullableIntExtra }
+ assertEquals(TextExtraActivity.DEFAULT_INT, activity.intDefaultExtra)
+ assertEquals(TextExtraActivity.DEFAULT_NULLABLE_INT, activity.nullableIntDefaultExtra)
+ }
+
+ private fun launchExtraActivity(configure: Intent.() -> Unit = {}): TextExtraActivity {
+ val intent = Intent().apply(configure)
+ return rule.launchActivity(intent)
+ }
+}
diff --git a/src/main/java/androidx/core/activity/Activity.kt b/src/main/java/androidx/core/activity/Activity.kt
new file mode 100644
index 00000000..d9c9eb9a
--- /dev/null
+++ b/src/main/java/androidx/core/activity/Activity.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.activity
+
+import android.app.Activity
+
+/**
+ * Returns a [Lazy] instance that parses the receiver's input intent and extracts an extra from type
+ * [T] mapped by the input [key].
+ *
+ * The returned value can be used as a property delegate, for instance:
+ *
+ * ```kotlin
+ * class MyActivity : Activity() {
+ *
+ * private val name by extra("name")
+ * }
+ * ```
+ *
+ * If such value can't be retrieved, an exception will be thrown. This will happen when:
+ *
+ * - There is an extra mapped by [key] and it can't be cast to [T]
+ * - There's no extra mapped by [key] and [T] is not a nullable type
+ *
+ * @param key The extra key
+ * @param T The extra type
+ * @return A [Lazy] that returns an intent extra
+ */
+inline fun Activity.extra(key: String): Lazy = lazy {
+ val value = intent.extras?.get(key)
+ if (value is T) {
+ value
+ } else {
+ throw IllegalArgumentException("Couldn't find extra with key \"$key\" from type " +
+ T::class.java.canonicalName)
+ }
+}
+
+/**
+ * Returns a [Lazy] instance that parses the receiver's input intent and extracts an extra from type
+ * [T] mapped by the input [key], returning the result of the [default] function in case the extra
+ * can't be extracted.
+ *
+ * The returned value can be used as a property delegate, for instance:
+ *
+ * ```kotlin
+ * class MyActivity : Activity() {
+ *
+ * private val name by extra("name") { "Default name" }
+ * }
+ * ```
+ *
+ * If such value can't be retrieved, the result from [default] will be returned. This will happen
+ * when:
+ *
+ * - There is an extra mapped by [key] and it can't be cast to [T]
+ * - There's no extra mapped by [key] and [T] is not a nullable type
+ *
+ * @param key The extra key
+ * @param default A function that returns the default value
+ * @param T The extra type
+ * @return A [Lazy] that returns an intent extra
+ */
+inline fun Activity.extra(key: String, crossinline default: () -> T): Lazy = lazy {
+ val value = intent.extras?.get(key)
+ if (value is T) value else default()
+}
\ No newline at end of file