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