Migration of RemoteInputIntent from WSL to AndroidX
Migrating class RemoteInputIntent from Wearable Support
Librabry to AndroidX wear:wear-input. Change include renaming
to RemoteInputIntentHelper and switching from public
String constants to helper functions.
Bug: 176490620
Test: Unit tests at androidx.wear.input.RemoteInputIntentHelperTest.kt
Relnote: "RemoteInputIntent class from
Wearable Support Librabry to AndroidX."
Change-Id: I47ceeb522f3d0d4ef9ab6078cee228b32b29c416
diff --git a/wear/wear-input/api/current.txt b/wear/wear-input/api/current.txt
index 622f1a3..dc46d45 100644
--- a/wear/wear-input/api/current.txt
+++ b/wear/wear-input/api/current.txt
@@ -7,6 +7,43 @@
method public android.os.Bundle getButtonInfo(android.content.Context, int);
}
+ @RequiresApi(android.os.Build.VERSION_CODES.N) public final class RemoteInputIntentHelper {
+ method public static android.content.Intent createActionRemoteInputIntent();
+ method public static String? getCancelLabelExtra(android.content.Intent intent);
+ method public static String? getConfirmLabelExtra(android.content.Intent intent);
+ method public static String? getInProgressLabelExtra(android.content.Intent intent);
+ method public static java.util.List<android.app.RemoteInput>? getRemoteInputsExtra(android.content.Intent intent);
+ method public static java.util.List<java.lang.CharSequence>? getSmartReplyContextExtra(android.content.Intent intent);
+ method public static String? getTitleExtra(android.content.Intent intent);
+ method public static boolean hasRemoteInputsExtra(android.content.Intent intent);
+ method public static boolean isActionRemoteInput(android.content.Intent intent);
+ method public static android.content.Intent putCancelLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putConfirmLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putInProgressLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putRemoteInputsExtra(android.content.Intent intent, java.util.List<android.app.RemoteInput> remoteInputs);
+ method public static android.content.Intent putSmartReplyContextExtra(android.content.Intent intent, java.util.List<? extends java.lang.CharSequence> smartReplyContext);
+ method public static android.content.Intent putTitleExtra(android.content.Intent intent, String title);
+ field public static final androidx.wear.input.RemoteInputIntentHelper.Companion Companion;
+ }
+
+ public static final class RemoteInputIntentHelper.Companion {
+ method public android.content.Intent createActionRemoteInputIntent();
+ method public String? getCancelLabelExtra(android.content.Intent intent);
+ method public String? getConfirmLabelExtra(android.content.Intent intent);
+ method public String? getInProgressLabelExtra(android.content.Intent intent);
+ method public java.util.List<android.app.RemoteInput>? getRemoteInputsExtra(android.content.Intent intent);
+ method public java.util.List<java.lang.CharSequence>? getSmartReplyContextExtra(android.content.Intent intent);
+ method public String? getTitleExtra(android.content.Intent intent);
+ method public boolean hasRemoteInputsExtra(android.content.Intent intent);
+ method public boolean isActionRemoteInput(android.content.Intent intent);
+ method public android.content.Intent putCancelLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putConfirmLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putInProgressLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putRemoteInputsExtra(android.content.Intent intent, java.util.List<android.app.RemoteInput> remoteInputs);
+ method public android.content.Intent putSmartReplyContextExtra(android.content.Intent intent, java.util.List<? extends java.lang.CharSequence> smartReplyContext);
+ method public android.content.Intent putTitleExtra(android.content.Intent intent, String title);
+ }
+
public final class WearableButtons {
method public static int getButtonCount(android.content.Context);
method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
diff --git a/wear/wear-input/api/public_plus_experimental_current.txt b/wear/wear-input/api/public_plus_experimental_current.txt
index 622f1a3..dc46d45 100644
--- a/wear/wear-input/api/public_plus_experimental_current.txt
+++ b/wear/wear-input/api/public_plus_experimental_current.txt
@@ -7,6 +7,43 @@
method public android.os.Bundle getButtonInfo(android.content.Context, int);
}
+ @RequiresApi(android.os.Build.VERSION_CODES.N) public final class RemoteInputIntentHelper {
+ method public static android.content.Intent createActionRemoteInputIntent();
+ method public static String? getCancelLabelExtra(android.content.Intent intent);
+ method public static String? getConfirmLabelExtra(android.content.Intent intent);
+ method public static String? getInProgressLabelExtra(android.content.Intent intent);
+ method public static java.util.List<android.app.RemoteInput>? getRemoteInputsExtra(android.content.Intent intent);
+ method public static java.util.List<java.lang.CharSequence>? getSmartReplyContextExtra(android.content.Intent intent);
+ method public static String? getTitleExtra(android.content.Intent intent);
+ method public static boolean hasRemoteInputsExtra(android.content.Intent intent);
+ method public static boolean isActionRemoteInput(android.content.Intent intent);
+ method public static android.content.Intent putCancelLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putConfirmLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putInProgressLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putRemoteInputsExtra(android.content.Intent intent, java.util.List<android.app.RemoteInput> remoteInputs);
+ method public static android.content.Intent putSmartReplyContextExtra(android.content.Intent intent, java.util.List<? extends java.lang.CharSequence> smartReplyContext);
+ method public static android.content.Intent putTitleExtra(android.content.Intent intent, String title);
+ field public static final androidx.wear.input.RemoteInputIntentHelper.Companion Companion;
+ }
+
+ public static final class RemoteInputIntentHelper.Companion {
+ method public android.content.Intent createActionRemoteInputIntent();
+ method public String? getCancelLabelExtra(android.content.Intent intent);
+ method public String? getConfirmLabelExtra(android.content.Intent intent);
+ method public String? getInProgressLabelExtra(android.content.Intent intent);
+ method public java.util.List<android.app.RemoteInput>? getRemoteInputsExtra(android.content.Intent intent);
+ method public java.util.List<java.lang.CharSequence>? getSmartReplyContextExtra(android.content.Intent intent);
+ method public String? getTitleExtra(android.content.Intent intent);
+ method public boolean hasRemoteInputsExtra(android.content.Intent intent);
+ method public boolean isActionRemoteInput(android.content.Intent intent);
+ method public android.content.Intent putCancelLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putConfirmLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putInProgressLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putRemoteInputsExtra(android.content.Intent intent, java.util.List<android.app.RemoteInput> remoteInputs);
+ method public android.content.Intent putSmartReplyContextExtra(android.content.Intent intent, java.util.List<? extends java.lang.CharSequence> smartReplyContext);
+ method public android.content.Intent putTitleExtra(android.content.Intent intent, String title);
+ }
+
public final class WearableButtons {
method public static int getButtonCount(android.content.Context);
method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
diff --git a/wear/wear-input/api/restricted_current.txt b/wear/wear-input/api/restricted_current.txt
index 622f1a3..dc46d45 100644
--- a/wear/wear-input/api/restricted_current.txt
+++ b/wear/wear-input/api/restricted_current.txt
@@ -7,6 +7,43 @@
method public android.os.Bundle getButtonInfo(android.content.Context, int);
}
+ @RequiresApi(android.os.Build.VERSION_CODES.N) public final class RemoteInputIntentHelper {
+ method public static android.content.Intent createActionRemoteInputIntent();
+ method public static String? getCancelLabelExtra(android.content.Intent intent);
+ method public static String? getConfirmLabelExtra(android.content.Intent intent);
+ method public static String? getInProgressLabelExtra(android.content.Intent intent);
+ method public static java.util.List<android.app.RemoteInput>? getRemoteInputsExtra(android.content.Intent intent);
+ method public static java.util.List<java.lang.CharSequence>? getSmartReplyContextExtra(android.content.Intent intent);
+ method public static String? getTitleExtra(android.content.Intent intent);
+ method public static boolean hasRemoteInputsExtra(android.content.Intent intent);
+ method public static boolean isActionRemoteInput(android.content.Intent intent);
+ method public static android.content.Intent putCancelLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putConfirmLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putInProgressLabelExtra(android.content.Intent intent, String label);
+ method public static android.content.Intent putRemoteInputsExtra(android.content.Intent intent, java.util.List<android.app.RemoteInput> remoteInputs);
+ method public static android.content.Intent putSmartReplyContextExtra(android.content.Intent intent, java.util.List<? extends java.lang.CharSequence> smartReplyContext);
+ method public static android.content.Intent putTitleExtra(android.content.Intent intent, String title);
+ field public static final androidx.wear.input.RemoteInputIntentHelper.Companion Companion;
+ }
+
+ public static final class RemoteInputIntentHelper.Companion {
+ method public android.content.Intent createActionRemoteInputIntent();
+ method public String? getCancelLabelExtra(android.content.Intent intent);
+ method public String? getConfirmLabelExtra(android.content.Intent intent);
+ method public String? getInProgressLabelExtra(android.content.Intent intent);
+ method public java.util.List<android.app.RemoteInput>? getRemoteInputsExtra(android.content.Intent intent);
+ method public java.util.List<java.lang.CharSequence>? getSmartReplyContextExtra(android.content.Intent intent);
+ method public String? getTitleExtra(android.content.Intent intent);
+ method public boolean hasRemoteInputsExtra(android.content.Intent intent);
+ method public boolean isActionRemoteInput(android.content.Intent intent);
+ method public android.content.Intent putCancelLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putConfirmLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putInProgressLabelExtra(android.content.Intent intent, String label);
+ method public android.content.Intent putRemoteInputsExtra(android.content.Intent intent, java.util.List<android.app.RemoteInput> remoteInputs);
+ method public android.content.Intent putSmartReplyContextExtra(android.content.Intent intent, java.util.List<? extends java.lang.CharSequence> smartReplyContext);
+ method public android.content.Intent putTitleExtra(android.content.Intent intent, String title);
+ }
+
public final class WearableButtons {
method public static int getButtonCount(android.content.Context);
method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
diff --git a/wear/wear-input/build.gradle b/wear/wear-input/build.gradle
index f8cd36d..f1b4d8b 100644
--- a/wear/wear-input/build.gradle
+++ b/wear/wear-input/build.gradle
@@ -22,10 +22,12 @@
plugins {
id("AndroidXPlugin")
id("com.android.library")
+ id("kotlin-android")
}
dependencies {
api("androidx.annotation:annotation:1.1.0")
+ api(KOTLIN_STDLIB)
testImplementation(ANDROIDX_TEST_EXT_JUNIT)
testImplementation(ANDROIDX_TEST_CORE)
diff --git a/wear/wear-input/src/main/java/androidx/wear/input/RemoteInputIntentHelper.kt b/wear/wear-input/src/main/java/androidx/wear/input/RemoteInputIntentHelper.kt
new file mode 100644
index 0000000..c38b11e
--- /dev/null
+++ b/wear/wear-input/src/main/java/androidx/wear/input/RemoteInputIntentHelper.kt
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2020 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.wear.input
+
+import android.app.RemoteInput
+import android.content.Intent
+import android.os.Build
+import androidx.annotation.NonNull
+import androidx.annotation.Nullable
+import androidx.annotation.RequiresApi
+
+/**
+ * Helper functions for supporting remote inputs through starting an [android.content.Intent].
+ *
+ *
+ * The following example prompts the user to provide input for one `RemoteInput` by
+ * starting an input activity.
+ *
+ * ```
+ * public const val KEY_QUICK_REPLY_TEXT: String = "quick_reply";
+ * val remoteInputs: List<RemoteInput> = listOf(
+ * new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT).setLabel("Quick reply").build()
+ * );
+ * val intent: Intent = createActionRemoteInputIntent();
+ * putRemoteInputsExtra(intent, remoteInputs)
+ * startActivity(intent);
+ * ```
+ * The intent returned via [android.app.Activity.onActivityResult] will contain the input results if
+ * collected. More information about accessing these results can be found in [RemoteInput].
+ */
+@RequiresApi(Build.VERSION_CODES.N)
+public class RemoteInputIntentHelper private constructor() {
+ public companion object {
+ private const val ACTION_REMOTE_INPUT: String =
+ "android.support.wearable.input.action.REMOTE_INPUT"
+
+ private const val EXTRA_REMOTE_INPUTS: String =
+ "android.support.wearable.input.extra.REMOTE_INPUTS"
+
+ private const val EXTRA_TITLE: String = "android.support.wearable.input.extra.TITLE"
+
+ private const val EXTRA_CANCEL_LABEL: String =
+ "android.support.wearable.input.extra.CANCEL_LABEL"
+
+ private const val EXTRA_CONFIRM_LABEL: String =
+ "android.support.wearable.input.extra.CONFIRM_LABEL"
+
+ private const val EXTRA_IN_PROGRESS_LABEL: String =
+ "android.support.wearable.input.extra.IN_PROGRESS_LABEL"
+
+ private const val EXTRA_SMART_REPLY_CONTEXT: String =
+ "android.support.wearable.input.extra.SMART_REPLY_CONTEXT"
+
+ /**
+ * Create an intent with action for remote input. This intent can be used to start an
+ * activity that will prompt the user for input. With the other helpers in this class to
+ * specify the intent extras, we can configure the behaviour of the input activity, such as
+ * specifying input be collected from a user by populating with an array of [RemoteInput]
+ * with [putRemoteInputsExtra].
+ *
+ * @return The created intent with action for remote input.
+ */
+ @JvmStatic
+ @NonNull
+ public fun createActionRemoteInputIntent(): Intent = Intent(ACTION_REMOTE_INPUT)
+
+ /**
+ * Checks whether the action of the given intent is for remote input.
+ */
+ @JvmStatic
+ public fun isActionRemoteInput(intent: Intent): Boolean =
+ intent.action == ACTION_REMOTE_INPUT
+
+ /**
+ * Returns the array of [RemoteInput] from the given [Intent] that specifies inputs to be
+ * collected from a user. Should be used with [Intent] created with [
+ * .createActionRemoteInputIntent].
+ *
+ * @param intent The intent with given data.
+ * @return The array of [RemoteInput] previously added with [.putRemoteInputsExtra] or null
+ * which means no user input required.
+ */
+ @JvmStatic
+ @Nullable
+ public fun getRemoteInputsExtra(intent: Intent): List<RemoteInput>? =
+ intent.getParcelableArrayListExtra(EXTRA_REMOTE_INPUTS)
+
+ /**
+ * Checks whether the given [Intent] has extra for the array of [RemoteInput].
+ */
+ @JvmStatic
+ public fun hasRemoteInputsExtra(intent: Intent): Boolean =
+ intent.hasExtra(EXTRA_REMOTE_INPUTS)
+
+ /**
+ * Adds the array of [RemoteInput] to the given [Intent] that specifies inputs collected
+ * from a user. Should be used with [Intent] created with [.createActionRemoteInputIntent].
+ *
+ * @param intent The intent with given data.
+ * @param remoteInputs The array of [RemoteInput] to be added.
+ */
+ @JvmStatic
+ @NonNull
+ public fun putRemoteInputsExtra(
+ intent: Intent,
+ remoteInputs: List<RemoteInput>
+ ): Intent = intent.putExtra(EXTRA_REMOTE_INPUTS, ArrayList(remoteInputs))
+
+ /**
+ * Returns the [String] from the given [Intent] that specifies what is displayed on top of
+ * the confirmation screen to describe the action.
+ *
+ * @param intent The intent with given data.
+ * @return The string previously added with [.putTitleExtra] or null if no value is found.
+ */
+ @JvmStatic
+ @Nullable
+ public fun getTitleExtra(intent: Intent): String? = intent.getStringExtra(EXTRA_TITLE)
+
+ /**
+ * Adds the [String] to the given [Intent] that specifies what is displayed on top of
+ * the confirmation screen to describe the action like "SMS" or "Email".
+ *
+ * @param intent The intent with given data.
+ * @param title The string to be added.
+ * @return The given intent.
+ */
+ @JvmStatic
+ @NonNull
+ public fun putTitleExtra(intent: Intent, title: String): Intent =
+ intent.putExtra(EXTRA_TITLE, title)
+
+ /**
+ * Returns the [String] from the given [Intent] that specifies what is displayed to
+ * cancel the action.
+ *
+ * @param intent The intent with given data.
+ * @return The string previously added with [.putCancelLabelExtra] or null if no value is
+ * found.
+ */
+ @JvmStatic
+ @Nullable
+ public fun getCancelLabelExtra(intent: Intent): String? =
+ intent.getStringExtra(EXTRA_CANCEL_LABEL)
+
+ /**
+ * Adds the [String] to the given [Intent] that specifies what is displayed to cancel the
+ * action. This is usually an imperative verb, like "Cancel". Defaults to Cancel.
+ *
+ * @param intent The intent with given data.
+ * @param label The string to be added.
+ * @return The given intent.
+ */
+ @JvmStatic
+ @NonNull
+ public fun putCancelLabelExtra(intent: Intent, label: String): Intent =
+ intent.putExtra(EXTRA_CANCEL_LABEL, label)
+
+ /**
+ * Returns the [String] from the given [Intent] that specifies what is displayed to
+ * confirm that the action should be executed.
+ *
+ * @param intent The intent with given data.
+ * @return The string previously added with [.putConfirmLabelExtra] or null if no value is
+ * found.
+ */
+ @JvmStatic
+ @Nullable
+ public fun getConfirmLabelExtra(intent: Intent): String? =
+ intent.getStringExtra(EXTRA_CONFIRM_LABEL)
+
+ /**
+ * Adds the [String] to the given [Intent] that specifies what is displayed to confirm that
+ * the action should be executed. This is usually an imperative verb like "Send".
+ * Defaults to "Send".
+ *
+ * @param intent The intent with given data.
+ * @param label The string to be added.
+ * @return The given intent.
+ */
+ @JvmStatic
+ @NonNull
+ public fun putConfirmLabelExtra(intent: Intent, label: String): Intent =
+ intent.putExtra(EXTRA_CONFIRM_LABEL, label)
+
+ /**
+ * Returns the [String] from the given [Intent] that specifies what is displayed while the
+ * wearable is preparing to automatically execute the action.
+ *
+ * @param intent The intent with given data.
+ * @return The string previously added with [.putInProgressLabelExtra] or null if no
+ * value is found.
+ */
+ @JvmStatic
+ @Nullable
+ public fun getInProgressLabelExtra(intent: Intent): String? =
+ intent.getStringExtra(EXTRA_IN_PROGRESS_LABEL)
+
+ /**
+ * Adds the [String] to the given [Intent] that specifies what is displayed while the
+ * wearable is preparing to automatically execute the action. This is usually a 'ing'
+ * verb ending in ellipsis like "Sending...". Defaults to "Sending...".
+ *
+ * @param intent The intent with given data.
+ * @param label The string to be added.
+ * @return The given intent.
+ */
+ @JvmStatic
+ @NonNull
+ public fun putInProgressLabelExtra(intent: Intent, label: String): Intent =
+ intent.putExtra(EXTRA_IN_PROGRESS_LABEL, label)
+
+ /**
+ * Returns the array of [CharSequence] from the given [Intent] that provides context for
+ * creating Smart Reply choices within a RemoteInput session.
+ *
+ * @param intent The intent with given data.
+ * @return The array of [CharSequence] previously added with [.putSmartReplyContext] or [
+ * .putSmartReplyContextExtra] or null if no value is found.
+ */
+ @JvmStatic
+ @Nullable
+ public fun getSmartReplyContextExtra(intent: Intent): List<CharSequence>? =
+ intent.getCharSequenceArrayListExtra(EXTRA_SMART_REPLY_CONTEXT)
+
+ /**
+ * Adds the array of [CharSequence] to the given [Intent] that provides context for
+ * creating Smart Reply choices within a RemoteInput session. The context should be
+ * incoming chat messages that a user will reply to using RemoteInput. Only incoming
+ * messages (messages from other users) should be passed via this extra.
+ *
+ * The messages should be in the order that they were received with the newest messages
+ * at the highest index of the CharSequence[]. For example, a possible value for this
+ * extra would be: ["hey", "where are you?"]. In this case, "where are you?" was the most
+ * recently received message.
+ *
+ * Passing a chat context into RemoteInput using this method does not guarantee that Smart
+ * Reply choices will be shown to a user.
+ *
+ * @param intent The intent with given data.
+ * @param smartReplyContext The string to be added.
+ * @return The given intent.
+ */
+ @JvmStatic
+ @NonNull
+ public fun putSmartReplyContextExtra(
+ intent: Intent,
+ smartReplyContext: List<CharSequence>
+ ): Intent = intent.putExtra(EXTRA_SMART_REPLY_CONTEXT, ArrayList(smartReplyContext))
+ }
+}
\ No newline at end of file
diff --git a/wear/wear-input/src/test/java/androidx/wear/input/RemoteInputIntentHelperTest.kt b/wear/wear-input/src/test/java/androidx/wear/input/RemoteInputIntentHelperTest.kt
new file mode 100644
index 0000000..2daadf3
--- /dev/null
+++ b/wear/wear-input/src/test/java/androidx/wear/input/RemoteInputIntentHelperTest.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2020 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.wear.input
+
+import android.app.RemoteInput
+import android.content.Intent
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(WearInputTestRunner::class)
+class RemoteInputIntentHelperTest {
+ private val remoteInputs: List<RemoteInput> = listOf(
+ RemoteInput.Builder("ri1").build(), RemoteInput.Builder("ri2").build()
+ )
+
+ @Test
+ fun testCreateIntentWithRemoteInputAction() {
+ val intent = RemoteInputIntentHelper.createActionRemoteInputIntent()
+ assertTrue(RemoteInputIntentHelper.isActionRemoteInput(intent))
+ }
+
+ @Test
+ fun testCreateIntentWithoutRemoteInputAction() {
+ val intent = Intent()
+ assertFalse(RemoteInputIntentHelper.isActionRemoteInput(intent))
+ }
+
+ @Test
+ fun testHasRemoteInputs() {
+ val intent = Intent()
+ RemoteInputIntentHelper.putRemoteInputsExtra(intent, remoteInputs)
+ assertTrue(RemoteInputIntentHelper.hasRemoteInputsExtra(intent))
+ }
+
+ @Test
+ fun testGetRemoteInputs() {
+ val intent = Intent()
+ RemoteInputIntentHelper.putRemoteInputsExtra(intent, remoteInputs)
+ assertEquals(remoteInputs, RemoteInputIntentHelper.getRemoteInputsExtra(intent))
+ }
+
+ @Test
+ fun testGetTitle() {
+ val intent = Intent()
+ val title = "Test Title"
+ RemoteInputIntentHelper.putTitleExtra(intent, title)
+ assertEquals(title, RemoteInputIntentHelper.getTitleExtra(intent))
+ }
+
+ @Test
+ fun testGetCancelLabel() {
+ val intent = Intent()
+ val title = "Test Cancel Label"
+ RemoteInputIntentHelper.putCancelLabelExtra(intent, title)
+ assertEquals(title, RemoteInputIntentHelper.getCancelLabelExtra(intent))
+ }
+
+ @Test
+ fun testGetConfirmationLabel() {
+ val intent = Intent()
+ val title = "Test Confirmation Label"
+ RemoteInputIntentHelper.putConfirmLabelExtra(intent, title)
+ assertEquals(title, RemoteInputIntentHelper.getConfirmLabelExtra(intent))
+ }
+
+ @Test
+ fun testGetInProgressLabel() {
+ val intent = Intent()
+ val title = "Test In Progress Label"
+ RemoteInputIntentHelper.putInProgressLabelExtra(intent, title)
+ assertEquals(title, RemoteInputIntentHelper.getInProgressLabelExtra(intent))
+ }
+
+ @Test
+ fun testGetSmartReplyContextFromIntent() {
+ val intent = Intent()
+ val smartReplyContext = listOf<CharSequence>("Test Reply 1", "Test Reply 2")
+ RemoteInputIntentHelper.putSmartReplyContextExtra(intent, smartReplyContext)
+ assertEquals(smartReplyContext, RemoteInputIntentHelper.getSmartReplyContextExtra(intent))
+ }
+}
\ No newline at end of file
diff --git a/wear/wear-input/src/test/java/androidx/wear/input/WearInputTestRunner.kt b/wear/wear-input/src/test/java/androidx/wear/input/WearInputTestRunner.kt
new file mode 100644
index 0000000..01ffe1c
--- /dev/null
+++ b/wear/wear-input/src/test/java/androidx/wear/input/WearInputTestRunner.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 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.wear.input
+
+import org.junit.runners.model.FrameworkMethod
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.internal.bytecode.InstrumentationConfiguration
+
+/**
+ * A [RobolectricTestRunner] for [androidx.wear.input] unit tests.
+ *
+ * It has instrumentation turned off for the [androidx.wear.input] package.
+ *
+ * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters
+ * companion objects, constructors with default values for parameters, and data classes with
+ * inline classes. We don't need shadowing of our classes because we want to use the actual
+ * objects in our tests.
+ */
+class WearInputTestRunner(testClass: Class<*>) : RobolectricTestRunner(testClass) {
+ override fun createClassLoaderConfig(method: FrameworkMethod): InstrumentationConfiguration =
+ InstrumentationConfiguration.Builder(
+ super.createClassLoaderConfig(method)
+ )
+ .doNotInstrumentPackage("androidx.wear.input")
+ .build()
+}
\ No newline at end of file
diff --git a/wear/wear-input/src/test/java/androidx/wear/input/WearableButtonsTest.java b/wear/wear-input/src/test/java/androidx/wear/input/WearableButtonsTest.java
index 1c1f420..a1b36f3 100644
--- a/wear/wear-input/src/test/java/androidx/wear/input/WearableButtonsTest.java
+++ b/wear/wear-input/src/test/java/androidx/wear/input/WearableButtonsTest.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.graphics.Point;
import android.graphics.drawable.RotateDrawable;
-import android.os.Build;
import android.provider.Settings;
import android.view.Display;
import android.view.KeyEvent;
@@ -30,14 +29,11 @@
import android.view.WindowManager;
import androidx.test.core.app.ApplicationProvider;
-import androidx.wear.input.testing.R;
import androidx.wear.input.testing.TestWearableButtonsProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
import org.robolectric.annotation.internal.DoNotInstrument;
import org.robolectric.shadows.ShadowDrawable;
@@ -45,9 +41,8 @@
import java.util.Map;
/** Unit tests for {@link WearableButtons}. */
-@RunWith(RobolectricTestRunner.class)
+@RunWith(WearInputTestRunner.class)
@DoNotInstrument
-@Config(sdk = Build.VERSION_CODES.P)
public class WearableButtonsTest {
private final Point mScreenSize = new Point(480, 480);
diff --git a/wear/wear-input/src/test/resources/robolectric.properties b/wear/wear-input/src/test/resources/robolectric.properties
new file mode 100644
index 0000000..8df5ac5
--- /dev/null
+++ b/wear/wear-input/src/test/resources/robolectric.properties
@@ -0,0 +1,20 @@
+#
+# Copyright 2021 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.
+#
+
+# Robolectric currently doesn't support API 30, so we have to explicitly specify 28 as the target
+# sdk for now.
+# TODO(b/177072877) Remove when no longer necessary.
+sdk=28