1 /* 2 * Copyright (C) 2006 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.app; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IIntentReceiver; 25 import android.content.IIntentSender; 26 import android.content.IntentSender; 27 import android.os.Bundle; 28 import android.os.RemoteException; 29 import android.os.Handler; 30 import android.os.IBinder; 31 import android.os.Parcel; 32 import android.os.Parcelable; 33 import android.os.UserHandle; 34 import android.util.AndroidException; 35 36 import java.lang.annotation.Retention; 37 import java.lang.annotation.RetentionPolicy; 38 39 /** 40 * A description of an Intent and target action to perform with it. Instances 41 * of this class are created with {@link #getActivity}, {@link #getActivities}, 42 * {@link #getBroadcast}, and {@link #getService}; the returned object can be 43 * handed to other applications so that they can perform the action you 44 * described on your behalf at a later time. 45 * 46 * <p>By giving a PendingIntent to another application, 47 * you are granting it the right to perform the operation you have specified 48 * as if the other application was yourself (with the same permissions and 49 * identity). As such, you should be careful about how you build the PendingIntent: 50 * almost always, for example, the base Intent you supply should have the component 51 * name explicitly set to one of your own components, to ensure it is ultimately 52 * sent there and nowhere else. 53 * 54 * <p>A PendingIntent itself is simply a reference to a token maintained by 55 * the system describing the original data used to retrieve it. This means 56 * that, even if its owning application's process is killed, the 57 * PendingIntent itself will remain usable from other processes that 58 * have been given it. If the creating application later re-retrieves the 59 * same kind of PendingIntent (same operation, same Intent action, data, 60 * categories, and components, and same flags), it will receive a PendingIntent 61 * representing the same token if that is still valid, and can thus call 62 * {@link #cancel} to remove it. 63 * 64 * <p>Because of this behavior, it is important to know when two Intents 65 * are considered to be the same for purposes of retrieving a PendingIntent. 66 * A common mistake people make is to create multiple PendingIntent objects 67 * with Intents that only vary in their "extra" contents, expecting to get 68 * a different PendingIntent each time. This does <em>not</em> happen. The 69 * parts of the Intent that are used for matching are the same ones defined 70 * by {@link Intent#filterEquals(Intent) Intent.filterEquals}. If you use two 71 * Intent objects that are equivalent as per 72 * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get 73 * the same PendingIntent for both of them. 74 * 75 * <p>There are two typical ways to deal with this. 76 * 77 * <p>If you truly need multiple distinct PendingIntent objects active at 78 * the same time (such as to use as two notifications that are both shown 79 * at the same time), then you will need to ensure there is something that 80 * is different about them to associate them with different PendingIntents. 81 * This may be any of the Intent attributes considered by 82 * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different 83 * request code integers supplied to {@link #getActivity}, {@link #getActivities}, 84 * {@link #getBroadcast}, or {@link #getService}. 85 * 86 * <p>If you only need one PendingIntent active at a time for any of the 87 * Intents you will use, then you can alternatively use the flags 88 * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either 89 * cancel or modify whatever current PendingIntent is associated with the 90 * Intent you are supplying. 91 */ 92 public final class PendingIntent implements Parcelable { 93 private final IIntentSender mTarget; 94 95 /** @hide */ 96 @IntDef(flag = true, 97 value = { 98 FLAG_ONE_SHOT, 99 FLAG_NO_CREATE, 100 FLAG_CANCEL_CURRENT, 101 FLAG_UPDATE_CURRENT, 102 103 Intent.FILL_IN_ACTION, 104 Intent.FILL_IN_DATA, 105 Intent.FILL_IN_CATEGORIES, 106 Intent.FILL_IN_COMPONENT, 107 Intent.FILL_IN_PACKAGE, 108 Intent.FILL_IN_SOURCE_BOUNDS, 109 Intent.FILL_IN_SELECTOR, 110 Intent.FILL_IN_CLIP_DATA 111 }) 112 @Retention(RetentionPolicy.SOURCE) 113 public @interface Flags {} 114 115 /** 116 * Flag indicating that this PendingIntent can be used only once. 117 * For use with {@link #getActivity}, {@link #getBroadcast}, and 118 * {@link #getService}. <p>If set, after 119 * {@link #send()} is called on it, it will be automatically 120 * canceled for you and any future attempt to send through it will fail. 121 */ 122 public static final int FLAG_ONE_SHOT = 1<<30; 123 /** 124 * Flag indicating that if the described PendingIntent does not 125 * already exist, then simply return null instead of creating it. 126 * For use with {@link #getActivity}, {@link #getBroadcast}, and 127 * {@link #getService}. 128 */ 129 public static final int FLAG_NO_CREATE = 1<<29; 130 /** 131 * Flag indicating that if the described PendingIntent already exists, 132 * the current one should be canceled before generating a new one. 133 * For use with {@link #getActivity}, {@link #getBroadcast}, and 134 * {@link #getService}. <p>You can use 135 * this to retrieve a new PendingIntent when you are only changing the 136 * extra data in the Intent; by canceling the previous pending intent, 137 * this ensures that only entities given the new data will be able to 138 * launch it. If this assurance is not an issue, consider 139 * {@link #FLAG_UPDATE_CURRENT}. 140 */ 141 public static final int FLAG_CANCEL_CURRENT = 1<<28; 142 /** 143 * Flag indicating that if the described PendingIntent already exists, 144 * then keep it but replace its extra data with what is in this new 145 * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and 146 * {@link #getService}. <p>This can be used if you are creating intents where only the 147 * extras change, and don't care that any entities that received your 148 * previous PendingIntent will be able to launch it with your new 149 * extras even if they are not explicitly given to it. 150 */ 151 public static final int FLAG_UPDATE_CURRENT = 1<<27; 152 153 /** 154 * Exception thrown when trying to send through a PendingIntent that 155 * has been canceled or is otherwise no longer able to execute the request. 156 */ 157 public static class CanceledException extends AndroidException { CanceledException()158 public CanceledException() { 159 } 160 CanceledException(String name)161 public CanceledException(String name) { 162 super(name); 163 } 164 CanceledException(Exception cause)165 public CanceledException(Exception cause) { 166 super(cause); 167 } 168 } 169 170 /** 171 * Callback interface for discovering when a send operation has 172 * completed. Primarily for use with a PendingIntent that is 173 * performing a broadcast, this provides the same information as 174 * calling {@link Context#sendOrderedBroadcast(Intent, String, 175 * android.content.BroadcastReceiver, Handler, int, String, Bundle) 176 * Context.sendBroadcast()} with a final BroadcastReceiver. 177 */ 178 public interface OnFinished { 179 /** 180 * Called when a send operation as completed. 181 * 182 * @param pendingIntent The PendingIntent this operation was sent through. 183 * @param intent The original Intent that was sent. 184 * @param resultCode The final result code determined by the send. 185 * @param resultData The final data collected by a broadcast. 186 * @param resultExtras The final extras collected by a broadcast. 187 */ onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)188 void onSendFinished(PendingIntent pendingIntent, Intent intent, 189 int resultCode, String resultData, Bundle resultExtras); 190 } 191 192 private static class FinishedDispatcher extends IIntentReceiver.Stub 193 implements Runnable { 194 private final PendingIntent mPendingIntent; 195 private final OnFinished mWho; 196 private final Handler mHandler; 197 private Intent mIntent; 198 private int mResultCode; 199 private String mResultData; 200 private Bundle mResultExtras; FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler)201 FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) { 202 mPendingIntent = pi; 203 mWho = who; 204 mHandler = handler; 205 } performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean serialized, boolean sticky, int sendingUser)206 public void performReceive(Intent intent, int resultCode, String data, 207 Bundle extras, boolean serialized, boolean sticky, int sendingUser) { 208 mIntent = intent; 209 mResultCode = resultCode; 210 mResultData = data; 211 mResultExtras = extras; 212 if (mHandler == null) { 213 run(); 214 } else { 215 mHandler.post(this); 216 } 217 } run()218 public void run() { 219 mWho.onSendFinished(mPendingIntent, mIntent, mResultCode, 220 mResultData, mResultExtras); 221 } 222 } 223 224 /** 225 * Retrieve a PendingIntent that will start a new activity, like calling 226 * {@link Context#startActivity(Intent) Context.startActivity(Intent)}. 227 * Note that the activity will be started outside of the context of an 228 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 229 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. 230 * 231 * <p class="note">For security reasons, the {@link android.content.Intent} 232 * you supply here should almost always be an <em>explicit intent</em>, 233 * that is specify an explicit component to be delivered to through 234 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 235 * 236 * @param context The Context in which this PendingIntent should start 237 * the activity. 238 * @param requestCode Private request code for the sender 239 * @param intent Intent of the activity to be launched. 240 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 241 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 242 * or any of the flags as supported by 243 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 244 * of the intent that can be supplied when the actual send happens. 245 * 246 * @return Returns an existing or new PendingIntent matching the given 247 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 248 * supplied. 249 */ getActivity(Context context, int requestCode, Intent intent, @Flags int flags)250 public static PendingIntent getActivity(Context context, int requestCode, 251 Intent intent, @Flags int flags) { 252 return getActivity(context, requestCode, intent, flags, null); 253 } 254 255 /** 256 * Retrieve a PendingIntent that will start a new activity, like calling 257 * {@link Context#startActivity(Intent) Context.startActivity(Intent)}. 258 * Note that the activity will be started outside of the context of an 259 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 260 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. 261 * 262 * <p class="note">For security reasons, the {@link android.content.Intent} 263 * you supply here should almost always be an <em>explicit intent</em>, 264 * that is specify an explicit component to be delivered to through 265 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 266 * 267 * @param context The Context in which this PendingIntent should start 268 * the activity. 269 * @param requestCode Private request code for the sender 270 * @param intent Intent of the activity to be launched. 271 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 272 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 273 * or any of the flags as supported by 274 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 275 * of the intent that can be supplied when the actual send happens. 276 * @param options Additional options for how the Activity should be started. 277 * May be null if there are no options. 278 * 279 * @return Returns an existing or new PendingIntent matching the given 280 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 281 * supplied. 282 */ getActivity(Context context, int requestCode, @NonNull Intent intent, @Flags int flags, @Nullable Bundle options)283 public static PendingIntent getActivity(Context context, int requestCode, 284 @NonNull Intent intent, @Flags int flags, @Nullable Bundle options) { 285 String packageName = context.getPackageName(); 286 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 287 context.getContentResolver()) : null; 288 try { 289 intent.migrateExtraStreamToClipData(); 290 intent.prepareToLeaveProcess(); 291 IIntentSender target = 292 ActivityManagerNative.getDefault().getIntentSender( 293 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 294 null, null, requestCode, new Intent[] { intent }, 295 resolvedType != null ? new String[] { resolvedType } : null, 296 flags, options, UserHandle.myUserId()); 297 return target != null ? new PendingIntent(target) : null; 298 } catch (RemoteException e) { 299 } 300 return null; 301 } 302 303 /** 304 * @hide 305 * Note that UserHandle.CURRENT will be interpreted at the time the 306 * activity is started, not when the pending intent is created. 307 */ getActivityAsUser(Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user)308 public static PendingIntent getActivityAsUser(Context context, int requestCode, 309 @NonNull Intent intent, int flags, Bundle options, UserHandle user) { 310 String packageName = context.getPackageName(); 311 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 312 context.getContentResolver()) : null; 313 try { 314 intent.migrateExtraStreamToClipData(); 315 intent.prepareToLeaveProcess(); 316 IIntentSender target = 317 ActivityManagerNative.getDefault().getIntentSender( 318 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 319 null, null, requestCode, new Intent[] { intent }, 320 resolvedType != null ? new String[] { resolvedType } : null, 321 flags, options, user.getIdentifier()); 322 return target != null ? new PendingIntent(target) : null; 323 } catch (RemoteException e) { 324 } 325 return null; 326 } 327 328 /** 329 * Like {@link #getActivity(Context, int, Intent, int)}, but allows an 330 * array of Intents to be supplied. The last Intent in the array is 331 * taken as the primary key for the PendingIntent, like the single Intent 332 * given to {@link #getActivity(Context, int, Intent, int)}. Upon sending 333 * the resulting PendingIntent, all of the Intents are started in the same 334 * way as they would be by passing them to {@link Context#startActivities(Intent[])}. 335 * 336 * <p class="note"> 337 * The <em>first</em> intent in the array will be started outside of the context of an 338 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 339 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. (Activities after 340 * the first in the array are started in the context of the previous activity 341 * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.) 342 * </p> 343 * 344 * <p class="note"> 345 * The <em>last</em> intent in the array represents the key for the 346 * PendingIntent. In other words, it is the significant element for matching 347 * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)}, 348 * its content will be the subject of replacement by 349 * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc. 350 * This is because it is the most specific of the supplied intents, and the 351 * UI the user actually sees when the intents are started. 352 * </p> 353 * 354 * <p class="note">For security reasons, the {@link android.content.Intent} objects 355 * you supply here should almost always be <em>explicit intents</em>, 356 * that is specify an explicit component to be delivered to through 357 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 358 * 359 * @param context The Context in which this PendingIntent should start 360 * the activity. 361 * @param requestCode Private request code for the sender 362 * @param intents Array of Intents of the activities to be launched. 363 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 364 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 365 * or any of the flags as supported by 366 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 367 * of the intent that can be supplied when the actual send happens. 368 * 369 * @return Returns an existing or new PendingIntent matching the given 370 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 371 * supplied. 372 */ getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags)373 public static PendingIntent getActivities(Context context, int requestCode, 374 @NonNull Intent[] intents, @Flags int flags) { 375 return getActivities(context, requestCode, intents, flags, null); 376 } 377 378 /** 379 * Like {@link #getActivity(Context, int, Intent, int)}, but allows an 380 * array of Intents to be supplied. The last Intent in the array is 381 * taken as the primary key for the PendingIntent, like the single Intent 382 * given to {@link #getActivity(Context, int, Intent, int)}. Upon sending 383 * the resulting PendingIntent, all of the Intents are started in the same 384 * way as they would be by passing them to {@link Context#startActivities(Intent[])}. 385 * 386 * <p class="note"> 387 * The <em>first</em> intent in the array will be started outside of the context of an 388 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 389 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. (Activities after 390 * the first in the array are started in the context of the previous activity 391 * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.) 392 * </p> 393 * 394 * <p class="note"> 395 * The <em>last</em> intent in the array represents the key for the 396 * PendingIntent. In other words, it is the significant element for matching 397 * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)}, 398 * its content will be the subject of replacement by 399 * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc. 400 * This is because it is the most specific of the supplied intents, and the 401 * UI the user actually sees when the intents are started. 402 * </p> 403 * 404 * <p class="note">For security reasons, the {@link android.content.Intent} objects 405 * you supply here should almost always be <em>explicit intents</em>, 406 * that is specify an explicit component to be delivered to through 407 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 408 * 409 * @param context The Context in which this PendingIntent should start 410 * the activity. 411 * @param requestCode Private request code for the sender 412 * @param intents Array of Intents of the activities to be launched. 413 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 414 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 415 * or any of the flags as supported by 416 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 417 * of the intent that can be supplied when the actual send happens. 418 * 419 * @return Returns an existing or new PendingIntent matching the given 420 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 421 * supplied. 422 */ getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options)423 public static PendingIntent getActivities(Context context, int requestCode, 424 @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options) { 425 String packageName = context.getPackageName(); 426 String[] resolvedTypes = new String[intents.length]; 427 for (int i=0; i<intents.length; i++) { 428 intents[i].migrateExtraStreamToClipData(); 429 intents[i].prepareToLeaveProcess(); 430 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); 431 } 432 try { 433 IIntentSender target = 434 ActivityManagerNative.getDefault().getIntentSender( 435 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 436 null, null, requestCode, intents, resolvedTypes, flags, options, 437 UserHandle.myUserId()); 438 return target != null ? new PendingIntent(target) : null; 439 } catch (RemoteException e) { 440 } 441 return null; 442 } 443 444 /** 445 * @hide 446 * Note that UserHandle.CURRENT will be interpreted at the time the 447 * activity is started, not when the pending intent is created. 448 */ getActivitiesAsUser(Context context, int requestCode, @NonNull Intent[] intents, int flags, Bundle options, UserHandle user)449 public static PendingIntent getActivitiesAsUser(Context context, int requestCode, 450 @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) { 451 String packageName = context.getPackageName(); 452 String[] resolvedTypes = new String[intents.length]; 453 for (int i=0; i<intents.length; i++) { 454 intents[i].migrateExtraStreamToClipData(); 455 intents[i].prepareToLeaveProcess(); 456 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); 457 } 458 try { 459 IIntentSender target = 460 ActivityManagerNative.getDefault().getIntentSender( 461 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 462 null, null, requestCode, intents, resolvedTypes, 463 flags, options, user.getIdentifier()); 464 return target != null ? new PendingIntent(target) : null; 465 } catch (RemoteException e) { 466 } 467 return null; 468 } 469 470 /** 471 * Retrieve a PendingIntent that will perform a broadcast, like calling 472 * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}. 473 * 474 * <p class="note">For security reasons, the {@link android.content.Intent} 475 * you supply here should almost always be an <em>explicit intent</em>, 476 * that is specify an explicit component to be delivered to through 477 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 478 * 479 * @param context The Context in which this PendingIntent should perform 480 * the broadcast. 481 * @param requestCode Private request code for the sender 482 * @param intent The Intent to be broadcast. 483 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 484 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 485 * or any of the flags as supported by 486 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 487 * of the intent that can be supplied when the actual send happens. 488 * 489 * @return Returns an existing or new PendingIntent matching the given 490 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 491 * supplied. 492 */ getBroadcast(Context context, int requestCode, Intent intent, @Flags int flags)493 public static PendingIntent getBroadcast(Context context, int requestCode, 494 Intent intent, @Flags int flags) { 495 return getBroadcastAsUser(context, requestCode, intent, flags, 496 new UserHandle(UserHandle.myUserId())); 497 } 498 499 /** 500 * @hide 501 * Note that UserHandle.CURRENT will be interpreted at the time the 502 * broadcast is sent, not when the pending intent is created. 503 */ getBroadcastAsUser(Context context, int requestCode, Intent intent, int flags, UserHandle userHandle)504 public static PendingIntent getBroadcastAsUser(Context context, int requestCode, 505 Intent intent, int flags, UserHandle userHandle) { 506 String packageName = context.getPackageName(); 507 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 508 context.getContentResolver()) : null; 509 try { 510 intent.prepareToLeaveProcess(); 511 IIntentSender target = 512 ActivityManagerNative.getDefault().getIntentSender( 513 ActivityManager.INTENT_SENDER_BROADCAST, packageName, 514 null, null, requestCode, new Intent[] { intent }, 515 resolvedType != null ? new String[] { resolvedType } : null, 516 flags, null, userHandle.getIdentifier()); 517 return target != null ? new PendingIntent(target) : null; 518 } catch (RemoteException e) { 519 } 520 return null; 521 } 522 523 /** 524 * Retrieve a PendingIntent that will start a service, like calling 525 * {@link Context#startService Context.startService()}. The start 526 * arguments given to the service will come from the extras of the Intent. 527 * 528 * <p class="note">For security reasons, the {@link android.content.Intent} 529 * you supply here should almost always be an <em>explicit intent</em>, 530 * that is specify an explicit component to be delivered to through 531 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 532 * 533 * @param context The Context in which this PendingIntent should start 534 * the service. 535 * @param requestCode Private request code for the sender 536 * @param intent An Intent describing the service to be started. 537 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 538 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 539 * or any of the flags as supported by 540 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 541 * of the intent that can be supplied when the actual send happens. 542 * 543 * @return Returns an existing or new PendingIntent matching the given 544 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 545 * supplied. 546 */ getService(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)547 public static PendingIntent getService(Context context, int requestCode, 548 @NonNull Intent intent, @Flags int flags) { 549 String packageName = context.getPackageName(); 550 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 551 context.getContentResolver()) : null; 552 try { 553 intent.prepareToLeaveProcess(); 554 IIntentSender target = 555 ActivityManagerNative.getDefault().getIntentSender( 556 ActivityManager.INTENT_SENDER_SERVICE, packageName, 557 null, null, requestCode, new Intent[] { intent }, 558 resolvedType != null ? new String[] { resolvedType } : null, 559 flags, null, UserHandle.myUserId()); 560 return target != null ? new PendingIntent(target) : null; 561 } catch (RemoteException e) { 562 } 563 return null; 564 } 565 566 /** 567 * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent 568 * 569 * @return Returns a IntentSender object that wraps the sender of PendingIntent 570 * 571 */ getIntentSender()572 public IntentSender getIntentSender() { 573 return new IntentSender(mTarget); 574 } 575 576 /** 577 * Cancel a currently active PendingIntent. Only the original application 578 * owning a PendingIntent can cancel it. 579 */ cancel()580 public void cancel() { 581 try { 582 ActivityManagerNative.getDefault().cancelIntentSender(mTarget); 583 } catch (RemoteException e) { 584 } 585 } 586 587 /** 588 * Perform the operation associated with this PendingIntent. 589 * 590 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 591 * 592 * @throws CanceledException Throws CanceledException if the PendingIntent 593 * is no longer allowing more intents to be sent through it. 594 */ send()595 public void send() throws CanceledException { 596 send(null, 0, null, null, null, null); 597 } 598 599 /** 600 * Perform the operation associated with this PendingIntent. 601 * 602 * @param code Result code to supply back to the PendingIntent's target. 603 * 604 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 605 * 606 * @throws CanceledException Throws CanceledException if the PendingIntent 607 * is no longer allowing more intents to be sent through it. 608 */ send(int code)609 public void send(int code) throws CanceledException { 610 send(null, code, null, null, null, null); 611 } 612 613 /** 614 * Perform the operation associated with this PendingIntent, allowing the 615 * caller to specify information about the Intent to use. 616 * 617 * @param context The Context of the caller. 618 * @param code Result code to supply back to the PendingIntent's target. 619 * @param intent Additional Intent data. See {@link Intent#fillIn 620 * Intent.fillIn()} for information on how this is applied to the 621 * original Intent. 622 * 623 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 624 * 625 * @throws CanceledException Throws CanceledException if the PendingIntent 626 * is no longer allowing more intents to be sent through it. 627 */ send(Context context, int code, Intent intent)628 public void send(Context context, int code, Intent intent) 629 throws CanceledException { 630 send(context, code, intent, null, null, null); 631 } 632 633 /** 634 * Perform the operation associated with this PendingIntent, allowing the 635 * caller to be notified when the send has completed. 636 * 637 * @param code Result code to supply back to the PendingIntent's target. 638 * @param onFinished The object to call back on when the send has 639 * completed, or null for no callback. 640 * @param handler Handler identifying the thread on which the callback 641 * should happen. If null, the callback will happen from the thread 642 * pool of the process. 643 * 644 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 645 * 646 * @throws CanceledException Throws CanceledException if the PendingIntent 647 * is no longer allowing more intents to be sent through it. 648 */ send(int code, OnFinished onFinished, Handler handler)649 public void send(int code, OnFinished onFinished, Handler handler) 650 throws CanceledException { 651 send(null, code, null, onFinished, handler, null); 652 } 653 654 /** 655 * Perform the operation associated with this PendingIntent, allowing the 656 * caller to specify information about the Intent to use and be notified 657 * when the send has completed. 658 * 659 * <p>For the intent parameter, a PendingIntent 660 * often has restrictions on which fields can be supplied here, based on 661 * how the PendingIntent was retrieved in {@link #getActivity}, 662 * {@link #getBroadcast}, or {@link #getService}. 663 * 664 * @param context The Context of the caller. This may be null if 665 * <var>intent</var> is also null. 666 * @param code Result code to supply back to the PendingIntent's target. 667 * @param intent Additional Intent data. See {@link Intent#fillIn 668 * Intent.fillIn()} for information on how this is applied to the 669 * original Intent. Use null to not modify the original Intent. 670 * @param onFinished The object to call back on when the send has 671 * completed, or null for no callback. 672 * @param handler Handler identifying the thread on which the callback 673 * should happen. If null, the callback will happen from the thread 674 * pool of the process. 675 * 676 * @see #send() 677 * @see #send(int) 678 * @see #send(Context, int, Intent) 679 * @see #send(int, android.app.PendingIntent.OnFinished, Handler) 680 * @see #send(Context, int, Intent, OnFinished, Handler, String) 681 * 682 * @throws CanceledException Throws CanceledException if the PendingIntent 683 * is no longer allowing more intents to be sent through it. 684 */ send(Context context, int code, Intent intent, OnFinished onFinished, Handler handler)685 public void send(Context context, int code, Intent intent, 686 OnFinished onFinished, Handler handler) throws CanceledException { 687 send(context, code, intent, onFinished, handler, null); 688 } 689 690 /** 691 * Perform the operation associated with this PendingIntent, allowing the 692 * caller to specify information about the Intent to use and be notified 693 * when the send has completed. 694 * 695 * <p>For the intent parameter, a PendingIntent 696 * often has restrictions on which fields can be supplied here, based on 697 * how the PendingIntent was retrieved in {@link #getActivity}, 698 * {@link #getBroadcast}, or {@link #getService}. 699 * 700 * @param context The Context of the caller. This may be null if 701 * <var>intent</var> is also null. 702 * @param code Result code to supply back to the PendingIntent's target. 703 * @param intent Additional Intent data. See {@link Intent#fillIn 704 * Intent.fillIn()} for information on how this is applied to the 705 * original Intent. Use null to not modify the original Intent. 706 * @param onFinished The object to call back on when the send has 707 * completed, or null for no callback. 708 * @param handler Handler identifying the thread on which the callback 709 * should happen. If null, the callback will happen from the thread 710 * pool of the process. 711 * @param requiredPermission Name of permission that a recipient of the PendingIntent 712 * is required to hold. This is only valid for broadcast intents, and 713 * corresponds to the permission argument in 714 * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}. 715 * If null, no permission is required. 716 * 717 * @see #send() 718 * @see #send(int) 719 * @see #send(Context, int, Intent) 720 * @see #send(int, android.app.PendingIntent.OnFinished, Handler) 721 * @see #send(Context, int, Intent, OnFinished, Handler) 722 * 723 * @throws CanceledException Throws CanceledException if the PendingIntent 724 * is no longer allowing more intents to be sent through it. 725 */ send(Context context, int code, Intent intent, OnFinished onFinished, Handler handler, String requiredPermission)726 public void send(Context context, int code, Intent intent, 727 OnFinished onFinished, Handler handler, String requiredPermission) 728 throws CanceledException { 729 try { 730 String resolvedType = intent != null ? 731 intent.resolveTypeIfNeeded(context.getContentResolver()) 732 : null; 733 int res = mTarget.send(code, intent, resolvedType, 734 onFinished != null 735 ? new FinishedDispatcher(this, onFinished, handler) 736 : null, 737 requiredPermission); 738 if (res < 0) { 739 throw new CanceledException(); 740 } 741 } catch (RemoteException e) { 742 throw new CanceledException(e); 743 } 744 } 745 746 /** 747 * @deprecated Renamed to {@link #getCreatorPackage()}. 748 */ 749 @Deprecated getTargetPackage()750 public String getTargetPackage() { 751 try { 752 return ActivityManagerNative.getDefault() 753 .getPackageForIntentSender(mTarget); 754 } catch (RemoteException e) { 755 // Should never happen. 756 return null; 757 } 758 } 759 760 /** 761 * Return the package name of the application that created this 762 * PendingIntent, that is the identity under which you will actually be 763 * sending the Intent. The returned string is supplied by the system, so 764 * that an application can not spoof its package. 765 * 766 * <p class="note">Be careful about how you use this. All this tells you is 767 * who created the PendingIntent. It does <strong>not</strong> tell you who 768 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 769 * passed between applications, so the PendingIntent you receive from an application 770 * could actually be one it received from another application, meaning the result 771 * you get here will identify the original application. Because of this, you should 772 * only use this information to identify who you expect to be interacting with 773 * through a {@link #send} call, not who gave you the PendingIntent.</p> 774 * 775 * @return The package name of the PendingIntent, or null if there is 776 * none associated with it. 777 */ 778 @Nullable getCreatorPackage()779 public String getCreatorPackage() { 780 try { 781 return ActivityManagerNative.getDefault() 782 .getPackageForIntentSender(mTarget); 783 } catch (RemoteException e) { 784 // Should never happen. 785 return null; 786 } 787 } 788 789 /** 790 * Return the uid of the application that created this 791 * PendingIntent, that is the identity under which you will actually be 792 * sending the Intent. The returned integer is supplied by the system, so 793 * that an application can not spoof its uid. 794 * 795 * <p class="note">Be careful about how you use this. All this tells you is 796 * who created the PendingIntent. It does <strong>not</strong> tell you who 797 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 798 * passed between applications, so the PendingIntent you receive from an application 799 * could actually be one it received from another application, meaning the result 800 * you get here will identify the original application. Because of this, you should 801 * only use this information to identify who you expect to be interacting with 802 * through a {@link #send} call, not who gave you the PendingIntent.</p> 803 * 804 * @return The uid of the PendingIntent, or -1 if there is 805 * none associated with it. 806 */ getCreatorUid()807 public int getCreatorUid() { 808 try { 809 return ActivityManagerNative.getDefault() 810 .getUidForIntentSender(mTarget); 811 } catch (RemoteException e) { 812 // Should never happen. 813 return -1; 814 } 815 } 816 817 /** 818 * Return the user handle of the application that created this 819 * PendingIntent, that is the user under which you will actually be 820 * sending the Intent. The returned UserHandle is supplied by the system, so 821 * that an application can not spoof its user. See 822 * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for 823 * more explanation of user handles. 824 * 825 * <p class="note">Be careful about how you use this. All this tells you is 826 * who created the PendingIntent. It does <strong>not</strong> tell you who 827 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 828 * passed between applications, so the PendingIntent you receive from an application 829 * could actually be one it received from another application, meaning the result 830 * you get here will identify the original application. Because of this, you should 831 * only use this information to identify who you expect to be interacting with 832 * through a {@link #send} call, not who gave you the PendingIntent.</p> 833 * 834 * @return The user handle of the PendingIntent, or null if there is 835 * none associated with it. 836 */ 837 @Nullable getCreatorUserHandle()838 public UserHandle getCreatorUserHandle() { 839 try { 840 int uid = ActivityManagerNative.getDefault() 841 .getUidForIntentSender(mTarget); 842 return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null; 843 } catch (RemoteException e) { 844 // Should never happen. 845 return null; 846 } 847 } 848 849 /** 850 * @hide 851 * Check to verify that this PendingIntent targets a specific package. 852 */ isTargetedToPackage()853 public boolean isTargetedToPackage() { 854 try { 855 return ActivityManagerNative.getDefault() 856 .isIntentSenderTargetedToPackage(mTarget); 857 } catch (RemoteException e) { 858 // Should never happen. 859 return false; 860 } 861 } 862 863 /** 864 * @hide 865 * Check whether this PendingIntent will launch an Activity. 866 */ isActivity()867 public boolean isActivity() { 868 try { 869 return ActivityManagerNative.getDefault() 870 .isIntentSenderAnActivity(mTarget); 871 } catch (RemoteException e) { 872 // Should never happen. 873 return false; 874 } 875 } 876 877 /** 878 * @hide 879 * Return the Intent of this PendingIntent. 880 */ getIntent()881 public Intent getIntent() { 882 try { 883 return ActivityManagerNative.getDefault() 884 .getIntentForIntentSender(mTarget); 885 } catch (RemoteException e) { 886 // Should never happen. 887 return null; 888 } 889 } 890 891 /** 892 * @hide 893 * Return descriptive tag for this PendingIntent. 894 */ getTag(String prefix)895 public String getTag(String prefix) { 896 try { 897 return ActivityManagerNative.getDefault() 898 .getTagForIntentSender(mTarget, prefix); 899 } catch (RemoteException e) { 900 // Should never happen. 901 return null; 902 } 903 } 904 905 /** 906 * Comparison operator on two PendingIntent objects, such that true 907 * is returned then they both represent the same operation from the 908 * same package. This allows you to use {@link #getActivity}, 909 * {@link #getBroadcast}, or {@link #getService} multiple times (even 910 * across a process being killed), resulting in different PendingIntent 911 * objects but whose equals() method identifies them as being the same 912 * operation. 913 */ 914 @Override equals(Object otherObj)915 public boolean equals(Object otherObj) { 916 if (otherObj instanceof PendingIntent) { 917 return mTarget.asBinder().equals(((PendingIntent)otherObj) 918 .mTarget.asBinder()); 919 } 920 return false; 921 } 922 923 @Override hashCode()924 public int hashCode() { 925 return mTarget.asBinder().hashCode(); 926 } 927 928 @Override toString()929 public String toString() { 930 StringBuilder sb = new StringBuilder(128); 931 sb.append("PendingIntent{"); 932 sb.append(Integer.toHexString(System.identityHashCode(this))); 933 sb.append(": "); 934 sb.append(mTarget != null ? mTarget.asBinder() : null); 935 sb.append('}'); 936 return sb.toString(); 937 } 938 describeContents()939 public int describeContents() { 940 return 0; 941 } 942 writeToParcel(Parcel out, int flags)943 public void writeToParcel(Parcel out, int flags) { 944 out.writeStrongBinder(mTarget.asBinder()); 945 } 946 947 public static final Parcelable.Creator<PendingIntent> CREATOR 948 = new Parcelable.Creator<PendingIntent>() { 949 public PendingIntent createFromParcel(Parcel in) { 950 IBinder target = in.readStrongBinder(); 951 return target != null ? new PendingIntent(target) : null; 952 } 953 954 public PendingIntent[] newArray(int size) { 955 return new PendingIntent[size]; 956 } 957 }; 958 959 /** 960 * Convenience function for writing either a PendingIntent or null pointer to 961 * a Parcel. You must use this with {@link #readPendingIntentOrNullFromParcel} 962 * for later reading it. 963 * 964 * @param sender The PendingIntent to write, or null. 965 * @param out Where to write the PendingIntent. 966 */ writePendingIntentOrNullToParcel(@ullable PendingIntent sender, @NonNull Parcel out)967 public static void writePendingIntentOrNullToParcel(@Nullable PendingIntent sender, 968 @NonNull Parcel out) { 969 out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() 970 : null); 971 } 972 973 /** 974 * Convenience function for reading either a Messenger or null pointer from 975 * a Parcel. You must have previously written the Messenger with 976 * {@link #writePendingIntentOrNullToParcel}. 977 * 978 * @param in The Parcel containing the written Messenger. 979 * 980 * @return Returns the Messenger read from the Parcel, or null if null had 981 * been written. 982 */ 983 @Nullable readPendingIntentOrNullFromParcel(@onNull Parcel in)984 public static PendingIntent readPendingIntentOrNullFromParcel(@NonNull Parcel in) { 985 IBinder b = in.readStrongBinder(); 986 return b != null ? new PendingIntent(b) : null; 987 } 988 PendingIntent(IIntentSender target)989 /*package*/ PendingIntent(IIntentSender target) { 990 mTarget = target; 991 } 992 PendingIntent(IBinder target)993 /*package*/ PendingIntent(IBinder target) { 994 mTarget = IIntentSender.Stub.asInterface(target); 995 } 996 997 /** @hide */ getTarget()998 public IIntentSender getTarget() { 999 return mTarget; 1000 } 1001 } 1002