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