• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v4.app;
18 
19 import android.content.Intent;
20 import android.os.Build;
21 import android.os.Bundle;
22 import android.util.Log;
23 
24 /**
25  * Helper for using the {@link android.app.RemoteInput} API
26  * introduced after API level 4 in a backwards compatible fashion.
27  */
28 public class RemoteInput extends RemoteInputCompatBase.RemoteInput {
29     private static final String TAG = "RemoteInput";
30 
31     /** Label used to denote the clip data type used for remote input transport */
32     public static final String RESULTS_CLIP_LABEL = RemoteInputCompatJellybean.RESULTS_CLIP_LABEL;
33 
34     /** Extra added to a clip data intent object to hold the results bundle. */
35     public static final String EXTRA_RESULTS_DATA = RemoteInputCompatJellybean.EXTRA_RESULTS_DATA;
36 
37     private final String mResultKey;
38     private final CharSequence mLabel;
39     private final CharSequence[] mChoices;
40     private final boolean mAllowFreeFormInput;
41     private final Bundle mExtras;
42 
RemoteInput(String resultKey, CharSequence label, CharSequence[] choices, boolean allowFreeFormInput, Bundle extras)43     RemoteInput(String resultKey, CharSequence label, CharSequence[] choices,
44             boolean allowFreeFormInput, Bundle extras) {
45         this.mResultKey = resultKey;
46         this.mLabel = label;
47         this.mChoices = choices;
48         this.mAllowFreeFormInput = allowFreeFormInput;
49         this.mExtras = extras;
50     }
51 
52     /**
53      * Get the key that the result of this input will be set in from the Bundle returned by
54      * {@link #getResultsFromIntent} when the {@link android.app.PendingIntent} is sent.
55      */
getResultKey()56     public String getResultKey() {
57         return mResultKey;
58     }
59 
60     /**
61      * Get the label to display to users when collecting this input.
62      */
getLabel()63     public CharSequence getLabel() {
64         return mLabel;
65     }
66 
67     /**
68      * Get possible input choices. This can be {@code null} if there are no choices to present.
69      */
getChoices()70     public CharSequence[] getChoices() {
71         return mChoices;
72     }
73 
74     /**
75      * Get whether or not users can provide an arbitrary value for
76      * input. If you set this to {@code false}, users must select one of the
77      * choices in {@link #getChoices}. An {@link IllegalArgumentException} is thrown
78      * if you set this to false and {@link #getChoices} returns {@code null} or empty.
79      */
getAllowFreeFormInput()80     public boolean getAllowFreeFormInput() {
81         return mAllowFreeFormInput;
82     }
83 
84     /**
85      * Get additional metadata carried around with this remote input.
86      */
getExtras()87     public Bundle getExtras() {
88         return mExtras;
89     }
90 
91     /**
92      * Builder class for {@link android.support.v4.app.RemoteInput} objects.
93      */
94     public static final class Builder {
95         private final String mResultKey;
96         private CharSequence mLabel;
97         private CharSequence[] mChoices;
98         private boolean mAllowFreeFormInput = true;
99         private Bundle mExtras = new Bundle();
100 
101         /**
102          * Create a builder object for {@link android.support.v4.app.RemoteInput} objects.
103          * @param resultKey the Bundle key that refers to this input when collected from the user
104          */
Builder(String resultKey)105         public Builder(String resultKey) {
106             if (resultKey == null) {
107                 throw new IllegalArgumentException("Result key can't be null");
108             }
109             mResultKey = resultKey;
110         }
111 
112         /**
113          * Set a label to be displayed to the user when collecting this input.
114          * @param label The label to show to users when they input a response.
115          * @return this object for method chaining
116          */
setLabel(CharSequence label)117         public Builder setLabel(CharSequence label) {
118             mLabel = label;
119             return this;
120         }
121 
122         /**
123          * Specifies choices available to the user to satisfy this input.
124          * @param choices an array of pre-defined choices for users input.
125          *        You must provide a non-null and non-empty array if
126          *        you disabled free form input using {@link #setAllowFreeFormInput}.
127          * @return this object for method chaining
128          */
setChoices(CharSequence[] choices)129         public Builder setChoices(CharSequence[] choices) {
130             mChoices = choices;
131             return this;
132         }
133 
134         /**
135          * Specifies whether the user can provide arbitrary values.
136          *
137          * @param allowFreeFormInput The default is {@code true}.
138          *         If you specify {@code false}, you must provide a non-null
139          *         and non-empty array to {@link #setChoices} or an
140          *         {@link IllegalArgumentException} is thrown.
141          * @return this object for method chaining
142          */
setAllowFreeFormInput(boolean allowFreeFormInput)143         public Builder setAllowFreeFormInput(boolean allowFreeFormInput) {
144             mAllowFreeFormInput = allowFreeFormInput;
145             return this;
146         }
147 
148         /**
149          * Merge additional metadata into this builder.
150          *
151          * <p>Values within the Bundle will replace existing extras values in this Builder.
152          *
153          * @see RemoteInput#getExtras
154          */
addExtras(Bundle extras)155         public Builder addExtras(Bundle extras) {
156             if (extras != null) {
157                 mExtras.putAll(extras);
158             }
159             return this;
160         }
161 
162         /**
163          * Get the metadata Bundle used by this Builder.
164          *
165          * <p>The returned Bundle is shared with this Builder.
166          */
getExtras()167         public Bundle getExtras() {
168             return mExtras;
169         }
170 
171         /**
172          * Combine all of the options that have been set and return a new
173          * {@link android.support.v4.app.RemoteInput} object.
174          */
build()175         public RemoteInput build() {
176             return new RemoteInput(mResultKey, mLabel, mChoices, mAllowFreeFormInput, mExtras);
177         }
178     }
179 
180     /**
181      * Get the remote input results bundle from an intent. The returned Bundle will
182      * contain a key/value for every result key populated by remote input collector.
183      * Use the {@link Bundle#getCharSequence(String)} method to retrieve a value.
184      * @param intent The intent object that fired in response to an action or content intent
185      *               which also had one or more remote input requested.
186      */
getResultsFromIntent(Intent intent)187     public static Bundle getResultsFromIntent(Intent intent) {
188         return IMPL.getResultsFromIntent(intent);
189     }
190 
191     /**
192      * Populate an intent object with the results gathered from remote input. This method
193      * should only be called by remote input collection services when sending results to a
194      * pending intent.
195      * @param remoteInputs The remote inputs for which results are being provided
196      * @param intent The intent to add remote inputs to. The {@link android.content.ClipData}
197      *               field of the intent will be modified to contain the results.
198      * @param results A bundle holding the remote input results. This bundle should
199      *                be populated with keys matching the result keys specified in
200      *                {@code remoteInputs} with values being the result per key.
201      */
addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results)202     public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
203             Bundle results) {
204         IMPL.addResultsToIntent(remoteInputs, intent, results);
205     }
206 
207     private static final Impl IMPL;
208 
209     interface Impl {
getResultsFromIntent(Intent intent)210         Bundle getResultsFromIntent(Intent intent);
addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results)211         void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
212                 Bundle results);
213     }
214 
215     static class ImplBase implements Impl {
216         @Override
getResultsFromIntent(Intent intent)217         public Bundle getResultsFromIntent(Intent intent) {
218             Log.w(TAG, "RemoteInput is only supported from API Level 16");
219             return null;
220         }
221 
222         @Override
addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results)223         public void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results) {
224             Log.w(TAG, "RemoteInput is only supported from API Level 16");
225         }
226     }
227 
228     static class ImplJellybean implements Impl {
229         @Override
getResultsFromIntent(Intent intent)230         public Bundle getResultsFromIntent(Intent intent) {
231             return RemoteInputCompatJellybean.getResultsFromIntent(intent);
232         }
233 
234         @Override
addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results)235         public void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results) {
236             RemoteInputCompatJellybean.addResultsToIntent(remoteInputs, intent, results);
237         }
238     }
239 
240     static class ImplApi20 implements Impl {
241         @Override
getResultsFromIntent(Intent intent)242         public Bundle getResultsFromIntent(Intent intent) {
243             return RemoteInputCompatApi20.getResultsFromIntent(intent);
244         }
245 
246         @Override
addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results)247         public void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results) {
248             RemoteInputCompatApi20.addResultsToIntent(remoteInputs, intent, results);
249         }
250     }
251 
252     static {
253         if (Build.VERSION.SDK_INT >= 20) {
254             IMPL = new ImplApi20();
255         } else if (Build.VERSION.SDK_INT >= 16) {
256             IMPL = new ImplJellybean();
257         } else {
258             IMPL = new ImplBase();
259         }
260     }
261 
262     /** @hide */
263     public static final Factory FACTORY = new Factory() {
264         @Override
265         public RemoteInput build(String resultKey,
266                 CharSequence label, CharSequence[] choices, boolean allowFreeFormInput,
267                 Bundle extras) {
268             return new RemoteInput(resultKey, label, choices, allowFreeFormInput, extras);
269         }
270 
271         @Override
272         public RemoteInput[] newArray(int size) {
273             return new RemoteInput[size];
274         }
275     };
276 }
277