Merge "Add support for audio-focused notifications."
This commit is contained in:
committed by
Android (Google) Code Review
commit
57bf4ea479
@@ -5027,6 +5027,7 @@ package android.app {
|
||||
field public static final int DEFAULT_LIGHTS = 4; // 0x4
|
||||
field public static final int DEFAULT_SOUND = 1; // 0x1
|
||||
field public static final int DEFAULT_VIBRATE = 2; // 0x2
|
||||
field public static final java.lang.String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
|
||||
field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
|
||||
field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
|
||||
field public static final java.lang.String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
|
||||
@@ -5110,6 +5111,7 @@ package android.app {
|
||||
method public android.app.Notification.Action clone();
|
||||
method public int describeContents();
|
||||
method public boolean getAllowGeneratedReplies();
|
||||
method public android.app.RemoteInput[] getDataOnlyRemoteInputs();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public android.graphics.drawable.Icon getIcon();
|
||||
method public android.app.RemoteInput[] getRemoteInputs();
|
||||
@@ -5576,14 +5578,18 @@ package android.app {
|
||||
}
|
||||
|
||||
public final class RemoteInput implements android.os.Parcelable {
|
||||
method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>);
|
||||
method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
|
||||
method public int describeContents();
|
||||
method public boolean getAllowFreeFormInput();
|
||||
method public java.util.Set<java.lang.String> getAllowedDataTypes();
|
||||
method public java.lang.CharSequence[] getChoices();
|
||||
method public static java.util.Map<java.lang.String, android.net.Uri> getDataResultsFromIntent(android.content.Intent, java.lang.String);
|
||||
method public android.os.Bundle getExtras();
|
||||
method public java.lang.CharSequence getLabel();
|
||||
method public java.lang.String getResultKey();
|
||||
method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
|
||||
method public boolean isDataOnly();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.RemoteInput> CREATOR;
|
||||
field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
|
||||
@@ -5595,6 +5601,7 @@ package android.app {
|
||||
method public android.app.RemoteInput.Builder addExtras(android.os.Bundle);
|
||||
method public android.app.RemoteInput build();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public android.app.RemoteInput.Builder setAllowDataType(java.lang.String, boolean);
|
||||
method public android.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
|
||||
method public android.app.RemoteInput.Builder setChoices(java.lang.CharSequence[]);
|
||||
method public android.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
|
||||
|
||||
@@ -5185,6 +5185,7 @@ package android.app {
|
||||
field public static final int DEFAULT_LIGHTS = 4; // 0x4
|
||||
field public static final int DEFAULT_SOUND = 1; // 0x1
|
||||
field public static final int DEFAULT_VIBRATE = 2; // 0x2
|
||||
field public static final java.lang.String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
|
||||
field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
|
||||
field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
|
||||
field public static final java.lang.String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
|
||||
@@ -5270,6 +5271,7 @@ package android.app {
|
||||
method public android.app.Notification.Action clone();
|
||||
method public int describeContents();
|
||||
method public boolean getAllowGeneratedReplies();
|
||||
method public android.app.RemoteInput[] getDataOnlyRemoteInputs();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public android.graphics.drawable.Icon getIcon();
|
||||
method public android.app.RemoteInput[] getRemoteInputs();
|
||||
@@ -5761,14 +5763,18 @@ package android.app {
|
||||
}
|
||||
|
||||
public final class RemoteInput implements android.os.Parcelable {
|
||||
method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>);
|
||||
method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
|
||||
method public int describeContents();
|
||||
method public boolean getAllowFreeFormInput();
|
||||
method public java.util.Set<java.lang.String> getAllowedDataTypes();
|
||||
method public java.lang.CharSequence[] getChoices();
|
||||
method public static java.util.Map<java.lang.String, android.net.Uri> getDataResultsFromIntent(android.content.Intent, java.lang.String);
|
||||
method public android.os.Bundle getExtras();
|
||||
method public java.lang.CharSequence getLabel();
|
||||
method public java.lang.String getResultKey();
|
||||
method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
|
||||
method public boolean isDataOnly();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.RemoteInput> CREATOR;
|
||||
field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
|
||||
@@ -5780,6 +5786,7 @@ package android.app {
|
||||
method public android.app.RemoteInput.Builder addExtras(android.os.Bundle);
|
||||
method public android.app.RemoteInput build();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public android.app.RemoteInput.Builder setAllowDataType(java.lang.String, boolean);
|
||||
method public android.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
|
||||
method public android.app.RemoteInput.Builder setChoices(java.lang.CharSequence[]);
|
||||
method public android.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
|
||||
|
||||
@@ -5037,6 +5037,7 @@ package android.app {
|
||||
field public static final int DEFAULT_LIGHTS = 4; // 0x4
|
||||
field public static final int DEFAULT_SOUND = 1; // 0x1
|
||||
field public static final int DEFAULT_VIBRATE = 2; // 0x2
|
||||
field public static final java.lang.String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
|
||||
field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
|
||||
field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
|
||||
field public static final java.lang.String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
|
||||
@@ -5120,6 +5121,7 @@ package android.app {
|
||||
method public android.app.Notification.Action clone();
|
||||
method public int describeContents();
|
||||
method public boolean getAllowGeneratedReplies();
|
||||
method public android.app.RemoteInput[] getDataOnlyRemoteInputs();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public android.graphics.drawable.Icon getIcon();
|
||||
method public android.app.RemoteInput[] getRemoteInputs();
|
||||
@@ -5587,14 +5589,18 @@ package android.app {
|
||||
}
|
||||
|
||||
public final class RemoteInput implements android.os.Parcelable {
|
||||
method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>);
|
||||
method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
|
||||
method public int describeContents();
|
||||
method public boolean getAllowFreeFormInput();
|
||||
method public java.util.Set<java.lang.String> getAllowedDataTypes();
|
||||
method public java.lang.CharSequence[] getChoices();
|
||||
method public static java.util.Map<java.lang.String, android.net.Uri> getDataResultsFromIntent(android.content.Intent, java.lang.String);
|
||||
method public android.os.Bundle getExtras();
|
||||
method public java.lang.CharSequence getLabel();
|
||||
method public java.lang.String getResultKey();
|
||||
method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
|
||||
method public boolean isDataOnly();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.RemoteInput> CREATOR;
|
||||
field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
|
||||
@@ -5606,6 +5612,7 @@ package android.app {
|
||||
method public android.app.RemoteInput.Builder addExtras(android.os.Bundle);
|
||||
method public android.app.RemoteInput build();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public android.app.RemoteInput.Builder setAllowDataType(java.lang.String, boolean);
|
||||
method public android.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
|
||||
method public android.app.RemoteInput.Builder setChoices(java.lang.CharSequence[]);
|
||||
method public android.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
|
||||
|
||||
@@ -988,6 +988,32 @@ public class Notification implements Parcelable
|
||||
*/
|
||||
public static final String EXTRA_CONTAINS_CUSTOM_VIEW = "android.contains.customView";
|
||||
|
||||
/**
|
||||
* {@link #extras} key: the audio contents of this notification.
|
||||
*
|
||||
* This is for use when rendering the notification on an audio-focused interface;
|
||||
* the audio contents are a complete sound sample that contains the contents/body of the
|
||||
* notification. This may be used in substitute of a Text-to-Speech reading of the
|
||||
* notification. For example if the notification represents a voice message this should point
|
||||
* to the audio of that message.
|
||||
*
|
||||
* The data stored under this key should be a String representation of a Uri that contains the
|
||||
* audio contents in one of the following formats: WAV, PCM 16-bit, AMR-WB.
|
||||
*
|
||||
* This extra is unnecessary if you are using {@code MessagingStyle} since each {@code Message}
|
||||
* has a field for holding data URI. That field can be used for audio.
|
||||
* See {@code Message#setData}.
|
||||
*
|
||||
* Example usage:
|
||||
* <pre>
|
||||
* {@code
|
||||
* Notification.Builder myBuilder = (build your Notification as normal);
|
||||
* myBuilder.getExtras().putString(EXTRA_AUDIO_CONTENTS_URI, myAudioUri.toString());
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public static final String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
|
||||
|
||||
/** @hide */
|
||||
@SystemApi
|
||||
public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
|
||||
@@ -1007,6 +1033,21 @@ public class Notification implements Parcelable
|
||||
* to attach actions.
|
||||
*/
|
||||
public static class Action implements Parcelable {
|
||||
/**
|
||||
* {@link #extras} key: Keys to a {@link Parcelable} {@link ArrayList} of
|
||||
* {@link RemoteInput}s.
|
||||
*
|
||||
* This is intended for {@link RemoteInput}s that only accept data, meaning
|
||||
* {@link RemoteInput#getAllowFreeFormInput} is false, {@link RemoteInput#getChoices}
|
||||
* is null or empty, and {@link RemoteInput#getAllowedDataTypes is non-null and not
|
||||
* empty. These {@link RemoteInput}s will be ignored by devices that do not
|
||||
* support non-text-based {@link RemoteInput}s. See {@link Builder#build}.
|
||||
*
|
||||
* You can test if a RemoteInput matches these constraints using
|
||||
* {@link RemoteInput#isDataOnly}.
|
||||
*/
|
||||
private static final String EXTRA_DATA_ONLY_INPUTS = "android.extra.DATA_ONLY_INPUTS";
|
||||
|
||||
private final Bundle mExtras;
|
||||
private Icon mIcon;
|
||||
private final RemoteInput[] mRemoteInputs;
|
||||
@@ -1097,12 +1138,27 @@ public class Notification implements Parcelable
|
||||
|
||||
/**
|
||||
* Get the list of inputs to be collected from the user when this action is sent.
|
||||
* May return null if no remote inputs were added.
|
||||
* May return null if no remote inputs were added. Only returns inputs which accept
|
||||
* a text input. For inputs which only accept data use {@link #getDataOnlyRemoteInputs}.
|
||||
*/
|
||||
public RemoteInput[] getRemoteInputs() {
|
||||
return mRemoteInputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of inputs to be collected from the user that ONLY accept data when this
|
||||
* action is sent. These remote inputs are guaranteed to return true on a call to
|
||||
* {@link RemoteInput#isDataOnly}.
|
||||
*
|
||||
* May return null if no data-only remote inputs were added.
|
||||
*
|
||||
* This method exists so that legacy RemoteInput collectors that pre-date the addition
|
||||
* of non-textual RemoteInputs do not access these remote inputs.
|
||||
*/
|
||||
public RemoteInput[] getDataOnlyRemoteInputs() {
|
||||
return (RemoteInput[]) mExtras.getParcelableArray(EXTRA_DATA_ONLY_INPUTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link Action} objects.
|
||||
*/
|
||||
@@ -1226,9 +1282,32 @@ public class Notification implements Parcelable
|
||||
* @return the built action
|
||||
*/
|
||||
public Action build() {
|
||||
RemoteInput[] remoteInputs = mRemoteInputs != null
|
||||
? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null;
|
||||
return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs,
|
||||
ArrayList<RemoteInput> dataOnlyInputs = new ArrayList<>();
|
||||
RemoteInput[] previousDataInputs =
|
||||
(RemoteInput[]) mExtras.getParcelableArray(EXTRA_DATA_ONLY_INPUTS);
|
||||
if (previousDataInputs == null) {
|
||||
for (RemoteInput input : previousDataInputs) {
|
||||
dataOnlyInputs.add(input);
|
||||
}
|
||||
}
|
||||
List<RemoteInput> textInputs = new ArrayList<>();
|
||||
if (mRemoteInputs != null) {
|
||||
for (RemoteInput input : mRemoteInputs) {
|
||||
if (input.isDataOnly()) {
|
||||
dataOnlyInputs.add(input);
|
||||
} else {
|
||||
textInputs.add(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!dataOnlyInputs.isEmpty()) {
|
||||
RemoteInput[] dataInputsArr =
|
||||
dataOnlyInputs.toArray(new RemoteInput[dataOnlyInputs.size()]);
|
||||
mExtras.putParcelableArray(EXTRA_DATA_ONLY_INPUTS, dataInputsArr);
|
||||
}
|
||||
RemoteInput[] textInputsArr = textInputs.isEmpty()
|
||||
? null : textInputs.toArray(new RemoteInput[textInputs.size()]);
|
||||
return new Action(mIcon, mTitle, mIntent, mExtras, textInputsArr,
|
||||
mAllowGeneratedReplies);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,14 @@ package android.app;
|
||||
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.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
|
||||
@@ -61,9 +66,13 @@ 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 results bundle. */
|
||||
/** 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";
|
||||
|
||||
// Flags bitwise-ored to mFlags
|
||||
private static final int FLAG_ALLOW_FREE_FORM_INPUT = 0x1;
|
||||
|
||||
@@ -75,14 +84,16 @@ public final class RemoteInput implements Parcelable {
|
||||
private final CharSequence[] mChoices;
|
||||
private final int mFlags;
|
||||
private final Bundle mExtras;
|
||||
private final ArraySet<String> mAllowedDataTypes;
|
||||
|
||||
private RemoteInput(String resultKey, CharSequence label, CharSequence[] choices,
|
||||
int flags, Bundle extras) {
|
||||
int flags, Bundle extras, ArraySet<String> allowedDataTypes) {
|
||||
this.mResultKey = resultKey;
|
||||
this.mLabel = label;
|
||||
this.mChoices = choices;
|
||||
this.mFlags = flags;
|
||||
this.mExtras = extras;
|
||||
this.mAllowedDataTypes = allowedDataTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +118,21 @@ public final class RemoteInput implements Parcelable {
|
||||
return mChoices;
|
||||
}
|
||||
|
||||
public Set<String> getAllowedDataTypes() {
|
||||
return mAllowedDataTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the input only accepts data, meaning {@link #getAllowFreeFormInput}
|
||||
* is false, {@link #getChoices} is null or empty, and {@link #getAllowedDataTypes is
|
||||
* non-null and not empty.
|
||||
*/
|
||||
public boolean isDataOnly() {
|
||||
return !getAllowFreeFormInput()
|
||||
&& (getChoices() == null || getChoices().length == 0)
|
||||
&& !getAllowedDataTypes().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether or not users can provide an arbitrary value for
|
||||
* input. If you set this to {@code false}, users must select one of the
|
||||
@@ -133,6 +159,7 @@ public final class RemoteInput implements Parcelable {
|
||||
private CharSequence[] mChoices;
|
||||
private int mFlags = DEFAULT_FLAGS;
|
||||
private Bundle mExtras = new Bundle();
|
||||
private final ArraySet<String> mAllowedDataTypes = new ArraySet<>();
|
||||
|
||||
/**
|
||||
* Create a builder object for {@link RemoteInput} objects.
|
||||
@@ -177,14 +204,34 @@ public final class RemoteInput implements Parcelable {
|
||||
/**
|
||||
* Specifies whether the user can provide arbitrary values.
|
||||
*
|
||||
* @param allowFreeFormInput The default is {@code true}.
|
||||
* If you specify {@code false}, you must provide a non-null
|
||||
* and non-empty array to {@link #setChoices} or an
|
||||
* @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
|
||||
*/
|
||||
public Builder setAllowDataType(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
|
||||
*/
|
||||
public Builder setAllowFreeFormInput(boolean allowFreeFormInput) {
|
||||
setFlag(mFlags, allowFreeFormInput);
|
||||
public Builder setAllowFreeFormInput(boolean allowFreeFormTextInput) {
|
||||
setFlag(mFlags, allowFreeFormTextInput);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -224,7 +271,8 @@ public final class RemoteInput implements Parcelable {
|
||||
* object.
|
||||
*/
|
||||
public RemoteInput build() {
|
||||
return new RemoteInput(mResultKey, mLabel, mChoices, mFlags, mExtras);
|
||||
return new RemoteInput(
|
||||
mResultKey, mLabel, mChoices, mFlags, mExtras, mAllowedDataTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,32 +282,68 @@ public final class RemoteInput implements Parcelable {
|
||||
mChoices = in.readCharSequenceArray();
|
||||
mFlags = in.readInt();
|
||||
mExtras = in.readBundle();
|
||||
mAllowedDataTypes = (ArraySet<String>) in.readArraySet(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the remote input results bundle from an intent. The returned Bundle will
|
||||
* contain a key/value for every result key populated by remote input collector.
|
||||
* Use the {@link Bundle#getCharSequence(String)} method to retrieve a value.
|
||||
* Similar as {@link #getResultsFromIntent} but retrieves data results for a
|
||||
* specific RemoteInput result. To retrieve a value use:
|
||||
* <pre>
|
||||
* {@code
|
||||
* Map<String, Uri> results =
|
||||
* RemoteInput.getDataResultsFromIntent(intent, REMOTE_INPUT_KEY);
|
||||
* if (results != null) {
|
||||
* Uri data = results.get(MIME_TYPE_OF_INTEREST);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @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<String, Uri> getDataResultsFromIntent(
|
||||
Intent intent, String remoteInputResultKey) {
|
||||
Intent clipDataIntent = getClipDataIntentFromIntent(intent);
|
||||
if (clipDataIntent == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Uri> results = new HashMap<>();
|
||||
Bundle extras = clipDataIntent.getExtras();
|
||||
for (String key : extras.keySet()) {
|
||||
if (key.startsWith(EXTRA_DATA_TYPE_RESULTS_DATA)) {
|
||||
String mimeType = key.substring(EXTRA_DATA_TYPE_RESULTS_DATA.length());
|
||||
if (mimeType == null || mimeType.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
Bundle bundle = clipDataIntent.getBundleExtra(key);
|
||||
String uriStr = bundle.getString(remoteInputResultKey);
|
||||
if (uriStr == null || uriStr.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
results.put(mimeType, Uri.parse(uriStr));
|
||||
}
|
||||
}
|
||||
return results.isEmpty() ? null : results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the remote input text results bundle from an intent. The returned Bundle will
|
||||
* contain a key/value for every result key populated with text by remote input collector.
|
||||
* Use the {@link Bundle#getCharSequence(String)} method to retrieve a value. For non-text
|
||||
* results use {@link #getDataResultsFromIntent}.
|
||||
* @param intent The intent object that fired in response to an action or content intent
|
||||
* which also had one or more remote input requested.
|
||||
*/
|
||||
public static Bundle getResultsFromIntent(Intent intent) {
|
||||
ClipData clipData = intent.getClipData();
|
||||
if (clipData == null) {
|
||||
Intent clipDataIntent = getClipDataIntentFromIntent(intent);
|
||||
if (clipDataIntent == null) {
|
||||
return null;
|
||||
}
|
||||
ClipDescription clipDescription = clipData.getDescription();
|
||||
if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
|
||||
return null;
|
||||
}
|
||||
if (clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) {
|
||||
return clipData.getItemAt(0).getIntent().getExtras().getParcelable(EXTRA_RESULTS_DATA);
|
||||
}
|
||||
return null;
|
||||
return clipDataIntent.getExtras().getParcelable(EXTRA_RESULTS_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate an intent object with the results gathered from remote input. This method
|
||||
* Populate an intent object with the text results gathered from remote input. This method
|
||||
* should only be called by remote input collection services when sending results to a
|
||||
* pending intent.
|
||||
* @param remoteInputs The remote inputs for which results are being provided
|
||||
@@ -267,20 +351,61 @@ public final class RemoteInput implements Parcelable {
|
||||
* field of the intent will be modified to contain the results.
|
||||
* @param results A bundle holding the remote input results. This bundle should
|
||||
* be populated with keys matching the result keys specified in
|
||||
* {@code remoteInputs} with values being the result per key.
|
||||
* {@code remoteInputs} with values being the CharSequence results per key.
|
||||
*/
|
||||
public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
|
||||
Bundle results) {
|
||||
Bundle resultsBundle = new Bundle();
|
||||
Intent clipDataIntent = getClipDataIntentFromIntent(intent);
|
||||
if (clipDataIntent == null) {
|
||||
clipDataIntent = new Intent(); // First time we've added a result.
|
||||
}
|
||||
Bundle resultsBundle = clipDataIntent.getBundleExtra(EXTRA_RESULTS_DATA);
|
||||
if (resultsBundle == null) {
|
||||
resultsBundle = new Bundle();
|
||||
}
|
||||
for (RemoteInput remoteInput : remoteInputs) {
|
||||
Object result = results.get(remoteInput.getResultKey());
|
||||
if (result instanceof CharSequence) {
|
||||
resultsBundle.putCharSequence(remoteInput.getResultKey(), (CharSequence) result);
|
||||
}
|
||||
}
|
||||
Intent clipIntent = new Intent();
|
||||
clipIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle);
|
||||
intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipIntent));
|
||||
clipDataIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle);
|
||||
intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #addResultsToIntent} but for setting data results.
|
||||
* @param remoteInput The remote input for which results are being provided
|
||||
* @param intent The intent to add remote input results to. The {@link ClipData}
|
||||
* field of the intent will be modified to contain the results.
|
||||
* @param results A map of mime type to the Uri result for that mime type.
|
||||
*/
|
||||
public static void addDataResultToIntent(RemoteInput remoteInput, Intent intent,
|
||||
Map<String, Uri> results) {
|
||||
Intent clipDataIntent = getClipDataIntentFromIntent(intent);
|
||||
if (clipDataIntent == null) {
|
||||
clipDataIntent = new Intent(); // First time we've added a result.
|
||||
}
|
||||
for (Map.Entry<String, Uri> entry : results.entrySet()) {
|
||||
String mimeType = entry.getKey();
|
||||
Uri uri = entry.getValue();
|
||||
if (mimeType == null) {
|
||||
continue;
|
||||
}
|
||||
Bundle resultsBundle =
|
||||
clipDataIntent.getBundleExtra(getExtraResultsKeyForData(mimeType));
|
||||
if (resultsBundle == null) {
|
||||
resultsBundle = new Bundle();
|
||||
}
|
||||
resultsBundle.putString(remoteInput.getResultKey(), uri.toString());
|
||||
|
||||
clipDataIntent.putExtra(getExtraResultsKeyForData(mimeType), resultsBundle);
|
||||
}
|
||||
intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
|
||||
}
|
||||
|
||||
private static String getExtraResultsKeyForData(String mimeType) {
|
||||
return EXTRA_DATA_TYPE_RESULTS_DATA + mimeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -295,6 +420,7 @@ public final class RemoteInput implements Parcelable {
|
||||
out.writeCharSequenceArray(mChoices);
|
||||
out.writeInt(mFlags);
|
||||
out.writeBundle(mExtras);
|
||||
out.writeArraySet(mAllowedDataTypes);
|
||||
}
|
||||
|
||||
public static final Creator<RemoteInput> CREATOR = new Creator<RemoteInput>() {
|
||||
@@ -308,4 +434,19 @@ public final class RemoteInput implements Parcelable {
|
||||
return new RemoteInput[size];
|
||||
}
|
||||
};
|
||||
|
||||
private static Intent getClipDataIntentFromIntent(Intent intent) {
|
||||
ClipData clipData = intent.getClipData();
|
||||
if (clipData == null) {
|
||||
return null;
|
||||
}
|
||||
ClipDescription clipDescription = clipData.getDescription();
|
||||
if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
|
||||
return null;
|
||||
}
|
||||
if (!clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) {
|
||||
return null;
|
||||
}
|
||||
return clipData.getItemAt(0).getIntent();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user