/* * Copyright (C) 2014 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 android.app; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ClipData; import android.content.ClipDescription; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.ArraySet; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * A {@code RemoteInput} object specifies input to be collected from a user to be passed along with * an intent inside a {@link android.app.PendingIntent} that is sent. * Always use {@link RemoteInput.Builder} to create instances of this class. *
See * Replying * to notifications for more information on how to use this class. * *
The following example adds a {@code RemoteInput} to a {@link Notification.Action}, * sets the result key as {@code quick_reply}, and sets the label as {@code Quick reply}. * Users are prompted to input a response when they trigger the action. The results are sent along * with the intent and can be retrieved with the result key (provided to the {@link Builder} * constructor) from the Bundle returned by {@link #getResultsFromIntent}. * *
* public static final String KEY_QUICK_REPLY_TEXT = "quick_reply"; * Notification.Action action = new Notification.Action.Builder( * R.drawable.reply, "Reply", actionIntent) * .addRemoteInput(new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT) * .setLabel("Quick reply").build()) * .build();* *
When the {@link android.app.PendingIntent} is fired, the intent inside will contain the * input results if collected. To access these results, use the {@link #getResultsFromIntent} * function. The result values will present under the result key passed to the {@link Builder} * constructor. * *
* public static final String KEY_QUICK_REPLY_TEXT = "quick_reply"; * Bundle results = RemoteInput.getResultsFromIntent(intent); * if (results != null) { * CharSequence quickReplyResult = results.getCharSequence(KEY_QUICK_REPLY_TEXT); * }*/ public final class RemoteInput implements Parcelable { /** Label used to denote the clip data type used for remote input transport */ public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results"; /** Extra added to a clip data intent object to hold the text results bundle. */ public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData"; /** Extra added to a clip data intent object to hold the data results bundle. */ private static final String EXTRA_DATA_TYPE_RESULTS_DATA = "android.remoteinput.dataTypeResultsData"; /** Extra added to a clip data intent object identifying the {@link Source} of the results. */ private static final String EXTRA_RESULTS_SOURCE = "android.remoteinput.resultsSource"; /** @hide */ @IntDef(prefix = {"SOURCE_"}, value = {SOURCE_FREE_FORM_INPUT, SOURCE_CHOICE}) @Retention(RetentionPolicy.SOURCE) public @interface Source {} /** The user manually entered the data. */ public static final int SOURCE_FREE_FORM_INPUT = 0; /** The user selected one of the choices from {@link #getChoices}. */ public static final int SOURCE_CHOICE = 1; /** @hide */ @IntDef(prefix = {"EDIT_CHOICES_BEFORE_SENDING_"}, value = {EDIT_CHOICES_BEFORE_SENDING_AUTO, EDIT_CHOICES_BEFORE_SENDING_DISABLED, EDIT_CHOICES_BEFORE_SENDING_ENABLED}) @Retention(RetentionPolicy.SOURCE) public @interface EditChoicesBeforeSending {} /** The platform will determine whether choices will be edited before being sent to the app. */ public static final int EDIT_CHOICES_BEFORE_SENDING_AUTO = 0; /** Tapping on a choice should send the input immediately, without letting the user edit it. */ public static final int EDIT_CHOICES_BEFORE_SENDING_DISABLED = 1; /** Tapping on a choice should let the user edit the input before it is sent to the app. */ public static final int EDIT_CHOICES_BEFORE_SENDING_ENABLED = 2; // Flags bitwise-ored to mFlags private static final int FLAG_ALLOW_FREE_FORM_INPUT = 0x1; // Default value for flags integer private static final int DEFAULT_FLAGS = FLAG_ALLOW_FREE_FORM_INPUT; private final String mResultKey; private final CharSequence mLabel; private final CharSequence[] mChoices; private final int mFlags; @EditChoicesBeforeSending private final int mEditChoicesBeforeSending; private final Bundle mExtras; private final ArraySet
Note: Starting in Android P, these choices will always be shown on phones if the app's * target SDK is >= P. However, these choices may also be rendered on other types of devices * regardless of target SDK. * * @param choices an array of pre-defined choices for users input. * You must provide a non-null and non-empty array if * you disabled free form input using {@link #setAllowFreeFormInput} * @return this object for method chaining */ @NonNull public Builder setChoices(@Nullable CharSequence[] choices) { if (choices == null) { mChoices = null; } else { mChoices = new CharSequence[choices.length]; for (int i = 0; i < choices.length; i++) { mChoices[i] = Notification.safeCharSequence(choices[i]); } } return this; } /** * Specifies whether the user can provide arbitrary values. This allows an input * to accept non-textual values. Examples of usage are an input that wants audio * or an image. * * @param mimeType A mime type that results are allowed to come in. * Be aware that text results (see {@link #setAllowFreeFormInput} * are allowed by default. If you do not want text results you will have to * pass false to {@code setAllowFreeFormInput} * @param doAllow Whether the mime type should be allowed or not * @return this object for method chaining */ @NonNull public Builder setAllowDataType(@NonNull String mimeType, boolean doAllow) { if (doAllow) { mAllowedDataTypes.add(mimeType); } else { mAllowedDataTypes.remove(mimeType); } return this; } /** * Specifies whether the user can provide arbitrary text values. * * @param allowFreeFormTextInput The default is {@code true}. * If you specify {@code false}, you must either provide a non-null * and non-empty array to {@link #setChoices}, or enable a data result * in {@code setAllowDataType}. Otherwise an * {@link IllegalArgumentException} is thrown * @return this object for method chaining */ @NonNull public Builder setAllowFreeFormInput(boolean allowFreeFormTextInput) { setFlag(FLAG_ALLOW_FREE_FORM_INPUT, allowFreeFormTextInput); return this; } /** * Specifies whether tapping on a choice should let the user edit the input before it is * sent to the app. The default is {@link #EDIT_CHOICES_BEFORE_SENDING_AUTO}. * * It cannot be used if {@link #setAllowFreeFormInput} has been set to false. */ @NonNull public Builder setEditChoicesBeforeSending( @EditChoicesBeforeSending int editChoicesBeforeSending) { mEditChoicesBeforeSending = editChoicesBeforeSending; return this; } /** * Merge additional metadata into this builder. * *
Values within the Bundle will replace existing extras values in this Builder. * * @see RemoteInput#getExtras */ @NonNull public Builder addExtras(@NonNull Bundle extras) { if (extras != null) { mExtras.putAll(extras); } return this; } /** * Get the metadata Bundle used by this Builder. * *
The returned Bundle is shared with this Builder.
*/
@NonNull
public Bundle getExtras() {
return mExtras;
}
private void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
} else {
mFlags &= ~mask;
}
}
/**
* Combine all of the options that have been set and return a new {@link RemoteInput}
* object.
*/
@NonNull
public RemoteInput build() {
return new RemoteInput(mResultKey, mLabel, mChoices, mFlags, mEditChoicesBeforeSending,
mExtras, mAllowedDataTypes);
}
}
private RemoteInput(Parcel in) {
mResultKey = in.readString();
mLabel = in.readCharSequence();
mChoices = in.readCharSequenceArray();
mFlags = in.readInt();
mEditChoicesBeforeSending = in.readInt();
mExtras = in.readBundle();
mAllowedDataTypes = (ArraySet
* {@code
* Map
* @param intent The intent object that fired in response to an action or content intent
* which also had one or more remote input requested.
* @param remoteInputResultKey The result key for the RemoteInput you want results for.
*/
public static Map