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 * almost always, for example, the base Intent you supply should 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 { 130 public CanceledException() { 131 } 132 133 public CanceledException(String name) { 134 super(name); 135 } 136 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 */ 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; 173 FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) { 174 mPendingIntent = pi; 175 mWho = who; 176 mHandler = handler; 177 } 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 } 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 * <p class="note">For security reasons, the {@link android.content.Intent} 204 * you supply here should almost always be an <em>explicit intent</em>, 205 * that is specify an explicit component to be delivered to through 206 * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p> 207 * 208 * @param context The Context in which this PendingIntent should start 209 * the activity. 210 * @param requestCode Private request code for the sender (currently 211 * not used). 212 * @param intent Intent of the activity to be launched. 213 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 214 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 215 * or any of the flags as supported by 216 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 217 * of the intent that can be supplied when the actual send happens. 218 * 219 * @return Returns an existing or new PendingIntent matching the given 220 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 221 * supplied. 222 */ 223 public static PendingIntent getActivity(Context context, int requestCode, 224 Intent intent, int flags) { 225 return getActivity(context, requestCode, intent, flags, null); 226 } 227 228 /** 229 * Retrieve a PendingIntent that will start a new activity, like calling 230 * {@link Context#startActivity(Intent) Context.startActivity(Intent)}. 231 * Note that the activity will be started outside of the context of an 232 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 233 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. 234 * 235 * <p class="note">For security reasons, the {@link android.content.Intent} 236 * you supply here should almost always be an <em>explicit intent</em>, 237 * that is specify an explicit component to be delivered to through 238 * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p> 239 * 240 * @param context The Context in which this PendingIntent should start 241 * the activity. 242 * @param requestCode Private request code for the sender (currently 243 * not used). 244 * @param intent Intent of the activity to be launched. 245 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 246 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 247 * or any of the flags as supported by 248 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 249 * of the intent that can be supplied when the actual send happens. 250 * @param options Additional options for how the Activity should be started. 251 * May be null if there are no options. 252 * 253 * @return Returns an existing or new PendingIntent matching the given 254 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 255 * supplied. 256 */ 257 public static PendingIntent getActivity(Context context, int requestCode, 258 Intent intent, int flags, Bundle options) { 259 String packageName = context.getPackageName(); 260 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 261 context.getContentResolver()) : null; 262 try { 263 intent.migrateExtraStreamToClipData(); 264 intent.prepareToLeaveProcess(); 265 IIntentSender target = 266 ActivityManagerNative.getDefault().getIntentSender( 267 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 268 null, null, requestCode, new Intent[] { intent }, 269 resolvedType != null ? new String[] { resolvedType } : null, 270 flags, options, UserHandle.myUserId()); 271 return target != null ? new PendingIntent(target) : null; 272 } catch (RemoteException e) { 273 } 274 return null; 275 } 276 277 /** 278 * @hide 279 * Note that UserHandle.CURRENT will be interpreted at the time the 280 * activity is started, not when the pending intent is created. 281 */ 282 public static PendingIntent getActivityAsUser(Context context, int requestCode, 283 Intent intent, int flags, Bundle options, UserHandle user) { 284 String packageName = context.getPackageName(); 285 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 286 context.getContentResolver()) : null; 287 try { 288 intent.migrateExtraStreamToClipData(); 289 intent.prepareToLeaveProcess(); 290 IIntentSender target = 291 ActivityManagerNative.getDefault().getIntentSender( 292 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 293 null, null, requestCode, new Intent[] { intent }, 294 resolvedType != null ? new String[] { resolvedType } : null, 295 flags, options, user.getIdentifier()); 296 return target != null ? new PendingIntent(target) : null; 297 } catch (RemoteException e) { 298 } 299 return null; 300 } 301 302 /** 303 * Like {@link #getActivity(Context, int, Intent, int)}, but allows an 304 * array of Intents to be supplied. The last Intent in the array is 305 * taken as the primary key for the PendingIntent, like the single Intent 306 * given to {@link #getActivity(Context, int, Intent, int)}. Upon sending 307 * the resulting PendingIntent, all of the Intents are started in the same 308 * way as they would be by passing them to {@link Context#startActivities(Intent[])}. 309 * 310 * <p class="note"> 311 * The <em>first</em> intent in the array will be started outside of the context of an 312 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 313 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. (Activities after 314 * the first in the array are started in the context of the previous activity 315 * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.) 316 * </p> 317 * 318 * <p class="note"> 319 * The <em>last</em> intent in the array represents the key for the 320 * PendingIntent. In other words, it is the significant element for matching 321 * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)}, 322 * its content will be the subject of replacement by 323 * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc. 324 * This is because it is the most specific of the supplied intents, and the 325 * UI the user actually sees when the intents are started. 326 * </p> 327 * 328 * <p class="note">For security reasons, the {@link android.content.Intent} objects 329 * you supply here should almost always be <em>explicit intents</em>, 330 * that is specify an explicit component to be delivered to through 331 * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p> 332 * 333 * @param context The Context in which this PendingIntent should start 334 * the activity. 335 * @param requestCode Private request code for the sender (currently 336 * not used). 337 * @param intents Array of Intents of the activities to be launched. 338 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 339 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 340 * or any of the flags as supported by 341 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 342 * of the intent that can be supplied when the actual send happens. 343 * 344 * @return Returns an existing or new PendingIntent matching the given 345 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 346 * supplied. 347 */ 348 public static PendingIntent getActivities(Context context, int requestCode, 349 Intent[] intents, int flags) { 350 return getActivities(context, requestCode, intents, flags, null); 351 } 352 353 /** 354 * Like {@link #getActivity(Context, int, Intent, int)}, but allows an 355 * array of Intents to be supplied. The last Intent in the array is 356 * taken as the primary key for the PendingIntent, like the single Intent 357 * given to {@link #getActivity(Context, int, Intent, int)}. Upon sending 358 * the resulting PendingIntent, all of the Intents are started in the same 359 * way as they would be by passing them to {@link Context#startActivities(Intent[])}. 360 * 361 * <p class="note"> 362 * The <em>first</em> intent in the array will be started outside of the context of an 363 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 364 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. (Activities after 365 * the first in the array are started in the context of the previous activity 366 * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.) 367 * </p> 368 * 369 * <p class="note"> 370 * The <em>last</em> intent in the array represents the key for the 371 * PendingIntent. In other words, it is the significant element for matching 372 * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)}, 373 * its content will be the subject of replacement by 374 * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc. 375 * This is because it is the most specific of the supplied intents, and the 376 * UI the user actually sees when the intents are started. 377 * </p> 378 * 379 * <p class="note">For security reasons, the {@link android.content.Intent} objects 380 * you supply here should almost always be <em>explicit intents</em>, 381 * that is specify an explicit component to be delivered to through 382 * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p> 383 * 384 * @param context The Context in which this PendingIntent should start 385 * the activity. 386 * @param requestCode Private request code for the sender (currently 387 * not used). 388 * @param intents Array of Intents of the activities to be launched. 389 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 390 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 391 * or any of the flags as supported by 392 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 393 * of the intent that can be supplied when the actual send happens. 394 * 395 * @return Returns an existing or new PendingIntent matching the given 396 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 397 * supplied. 398 */ 399 public static PendingIntent getActivities(Context context, int requestCode, 400 Intent[] intents, int flags, Bundle options) { 401 String packageName = context.getPackageName(); 402 String[] resolvedTypes = new String[intents.length]; 403 for (int i=0; i<intents.length; i++) { 404 intents[i].migrateExtraStreamToClipData(); 405 intents[i].prepareToLeaveProcess(); 406 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); 407 } 408 try { 409 IIntentSender target = 410 ActivityManagerNative.getDefault().getIntentSender( 411 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 412 null, null, requestCode, intents, resolvedTypes, flags, options, 413 UserHandle.myUserId()); 414 return target != null ? new PendingIntent(target) : null; 415 } catch (RemoteException e) { 416 } 417 return null; 418 } 419 420 /** 421 * @hide 422 * Note that UserHandle.CURRENT will be interpreted at the time the 423 * activity is started, not when the pending intent is created. 424 */ 425 public static PendingIntent getActivitiesAsUser(Context context, int requestCode, 426 Intent[] intents, int flags, Bundle options, UserHandle user) { 427 String packageName = context.getPackageName(); 428 String[] resolvedTypes = new String[intents.length]; 429 for (int i=0; i<intents.length; i++) { 430 intents[i].migrateExtraStreamToClipData(); 431 intents[i].prepareToLeaveProcess(); 432 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); 433 } 434 try { 435 IIntentSender target = 436 ActivityManagerNative.getDefault().getIntentSender( 437 ActivityManager.INTENT_SENDER_ACTIVITY, packageName, 438 null, null, requestCode, intents, resolvedTypes, 439 flags, options, user.getIdentifier()); 440 return target != null ? new PendingIntent(target) : null; 441 } catch (RemoteException e) { 442 } 443 return null; 444 } 445 446 /** 447 * Retrieve a PendingIntent that will perform a broadcast, like calling 448 * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}. 449 * 450 * <p class="note">For security reasons, the {@link android.content.Intent} 451 * you supply here should almost always be an <em>explicit intent</em>, 452 * that is specify an explicit component to be delivered to through 453 * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p> 454 * 455 * @param context The Context in which this PendingIntent should perform 456 * the broadcast. 457 * @param requestCode Private request code for the sender (currently 458 * not used). 459 * @param intent The Intent to be broadcast. 460 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 461 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 462 * or any of the flags as supported by 463 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 464 * of the intent that can be supplied when the actual send happens. 465 * 466 * @return Returns an existing or new PendingIntent matching the given 467 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 468 * supplied. 469 */ 470 public static PendingIntent getBroadcast(Context context, int requestCode, 471 Intent intent, int flags) { 472 return getBroadcastAsUser(context, requestCode, intent, flags, 473 new UserHandle(UserHandle.myUserId())); 474 } 475 476 /** 477 * @hide 478 * Note that UserHandle.CURRENT will be interpreted at the time the 479 * broadcast is sent, not when the pending intent is created. 480 */ 481 public static PendingIntent getBroadcastAsUser(Context context, int requestCode, 482 Intent intent, int flags, UserHandle userHandle) { 483 String packageName = context.getPackageName(); 484 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 485 context.getContentResolver()) : null; 486 try { 487 intent.prepareToLeaveProcess(); 488 IIntentSender target = 489 ActivityManagerNative.getDefault().getIntentSender( 490 ActivityManager.INTENT_SENDER_BROADCAST, packageName, 491 null, null, requestCode, new Intent[] { intent }, 492 resolvedType != null ? new String[] { resolvedType } : null, 493 flags, null, userHandle.getIdentifier()); 494 return target != null ? new PendingIntent(target) : null; 495 } catch (RemoteException e) { 496 } 497 return null; 498 } 499 500 /** 501 * Retrieve a PendingIntent that will start a service, like calling 502 * {@link Context#startService Context.startService()}. The start 503 * arguments given to the service will come from the extras of the Intent. 504 * 505 * <p class="note">For security reasons, the {@link android.content.Intent} 506 * you supply here should almost always be an <em>explicit intent</em>, 507 * that is specify an explicit component to be delivered to through 508 * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p> 509 * 510 * @param context The Context in which this PendingIntent should start 511 * the service. 512 * @param requestCode Private request code for the sender (currently 513 * not used). 514 * @param intent An Intent describing the service to be started. 515 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 516 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 517 * or any of the flags as supported by 518 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 519 * of the intent that can be supplied when the actual send happens. 520 * 521 * @return Returns an existing or new PendingIntent matching the given 522 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 523 * supplied. 524 */ 525 public static PendingIntent getService(Context context, int requestCode, 526 Intent intent, int flags) { 527 String packageName = context.getPackageName(); 528 String resolvedType = intent != null ? intent.resolveTypeIfNeeded( 529 context.getContentResolver()) : null; 530 try { 531 intent.prepareToLeaveProcess(); 532 IIntentSender target = 533 ActivityManagerNative.getDefault().getIntentSender( 534 ActivityManager.INTENT_SENDER_SERVICE, packageName, 535 null, null, requestCode, new Intent[] { intent }, 536 resolvedType != null ? new String[] { resolvedType } : null, 537 flags, null, UserHandle.myUserId()); 538 return target != null ? new PendingIntent(target) : null; 539 } catch (RemoteException e) { 540 } 541 return null; 542 } 543 544 /** 545 * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent 546 * 547 * @return Returns a IntentSender object that wraps the sender of PendingIntent 548 * 549 */ 550 public IntentSender getIntentSender() { 551 return new IntentSender(mTarget); 552 } 553 554 /** 555 * Cancel a currently active PendingIntent. Only the original application 556 * owning a PendingIntent can cancel it. 557 */ 558 public void cancel() { 559 try { 560 ActivityManagerNative.getDefault().cancelIntentSender(mTarget); 561 } catch (RemoteException e) { 562 } 563 } 564 565 /** 566 * Perform the operation associated with this PendingIntent. 567 * 568 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 569 * 570 * @throws CanceledException Throws CanceledException if the PendingIntent 571 * is no longer allowing more intents to be sent through it. 572 */ 573 public void send() throws CanceledException { 574 send(null, 0, null, null, null, null); 575 } 576 577 /** 578 * Perform the operation associated with this PendingIntent. 579 * 580 * @param code Result code to supply back to the PendingIntent's target. 581 * 582 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 583 * 584 * @throws CanceledException Throws CanceledException if the PendingIntent 585 * is no longer allowing more intents to be sent through it. 586 */ 587 public void send(int code) throws CanceledException { 588 send(null, code, null, null, null, null); 589 } 590 591 /** 592 * Perform the operation associated with this PendingIntent, allowing the 593 * caller to specify information about the Intent to use. 594 * 595 * @param context The Context of the caller. 596 * @param code Result code to supply back to the PendingIntent's target. 597 * @param intent Additional Intent data. See {@link Intent#fillIn 598 * Intent.fillIn()} for information on how this is applied to the 599 * original Intent. 600 * 601 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 602 * 603 * @throws CanceledException Throws CanceledException if the PendingIntent 604 * is no longer allowing more intents to be sent through it. 605 */ 606 public void send(Context context, int code, Intent intent) 607 throws CanceledException { 608 send(context, code, intent, null, null, null); 609 } 610 611 /** 612 * Perform the operation associated with this PendingIntent, allowing the 613 * caller to be notified when the send has completed. 614 * 615 * @param code Result code to supply back to the PendingIntent's target. 616 * @param onFinished The object to call back on when the send has 617 * completed, or null for no callback. 618 * @param handler Handler identifying the thread on which the callback 619 * should happen. If null, the callback will happen from the thread 620 * pool of the process. 621 * 622 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler) 623 * 624 * @throws CanceledException Throws CanceledException if the PendingIntent 625 * is no longer allowing more intents to be sent through it. 626 */ 627 public void send(int code, OnFinished onFinished, Handler handler) 628 throws CanceledException { 629 send(null, code, null, onFinished, handler, null); 630 } 631 632 /** 633 * Perform the operation associated with this PendingIntent, allowing the 634 * caller to specify information about the Intent to use and be notified 635 * when the send has completed. 636 * 637 * <p>For the intent parameter, a PendingIntent 638 * often has restrictions on which fields can be supplied here, based on 639 * how the PendingIntent was retrieved in {@link #getActivity}, 640 * {@link #getBroadcast}, or {@link #getService}. 641 * 642 * @param context The Context of the caller. This may be null if 643 * <var>intent</var> is also null. 644 * @param code Result code to supply back to the PendingIntent's target. 645 * @param intent Additional Intent data. See {@link Intent#fillIn 646 * Intent.fillIn()} for information on how this is applied to the 647 * original Intent. Use null to not modify the original Intent. 648 * @param onFinished The object to call back on when the send has 649 * completed, or null for no callback. 650 * @param handler Handler identifying the thread on which the callback 651 * should happen. If null, the callback will happen from the thread 652 * pool of the process. 653 * 654 * @see #send() 655 * @see #send(int) 656 * @see #send(Context, int, Intent) 657 * @see #send(int, android.app.PendingIntent.OnFinished, Handler) 658 * @see #send(Context, int, Intent, OnFinished, Handler, String) 659 * 660 * @throws CanceledException Throws CanceledException if the PendingIntent 661 * is no longer allowing more intents to be sent through it. 662 */ 663 public void send(Context context, int code, Intent intent, 664 OnFinished onFinished, Handler handler) throws CanceledException { 665 send(context, code, intent, onFinished, handler, null); 666 } 667 668 /** 669 * Perform the operation associated with this PendingIntent, allowing the 670 * caller to specify information about the Intent to use and be notified 671 * when the send has completed. 672 * 673 * <p>For the intent parameter, a PendingIntent 674 * often has restrictions on which fields can be supplied here, based on 675 * how the PendingIntent was retrieved in {@link #getActivity}, 676 * {@link #getBroadcast}, or {@link #getService}. 677 * 678 * @param context The Context of the caller. This may be null if 679 * <var>intent</var> is also null. 680 * @param code Result code to supply back to the PendingIntent's target. 681 * @param intent Additional Intent data. See {@link Intent#fillIn 682 * Intent.fillIn()} for information on how this is applied to the 683 * original Intent. Use null to not modify the original Intent. 684 * @param onFinished The object to call back on when the send has 685 * completed, or null for no callback. 686 * @param handler Handler identifying the thread on which the callback 687 * should happen. If null, the callback will happen from the thread 688 * pool of the process. 689 * @param requiredPermission Name of permission that a recipient of the PendingIntent 690 * is required to hold. This is only valid for broadcast intents, and 691 * corresponds to the permission argument in 692 * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}. 693 * If null, no permission is required. 694 * 695 * @see #send() 696 * @see #send(int) 697 * @see #send(Context, int, Intent) 698 * @see #send(int, android.app.PendingIntent.OnFinished, Handler) 699 * @see #send(Context, int, Intent, OnFinished, Handler) 700 * 701 * @throws CanceledException Throws CanceledException if the PendingIntent 702 * is no longer allowing more intents to be sent through it. 703 */ 704 public void send(Context context, int code, Intent intent, 705 OnFinished onFinished, Handler handler, String requiredPermission) 706 throws CanceledException { 707 try { 708 String resolvedType = intent != null ? 709 intent.resolveTypeIfNeeded(context.getContentResolver()) 710 : null; 711 int res = mTarget.send(code, intent, resolvedType, 712 onFinished != null 713 ? new FinishedDispatcher(this, onFinished, handler) 714 : null, 715 requiredPermission); 716 if (res < 0) { 717 throw new CanceledException(); 718 } 719 } catch (RemoteException e) { 720 throw new CanceledException(e); 721 } 722 } 723 724 /** 725 * @deprecated Renamed to {@link #getCreatorPackage()}. 726 */ 727 @Deprecated 728 public String getTargetPackage() { 729 try { 730 return ActivityManagerNative.getDefault() 731 .getPackageForIntentSender(mTarget); 732 } catch (RemoteException e) { 733 // Should never happen. 734 return null; 735 } 736 } 737 738 /** 739 * Return the package name of the application that created this 740 * PendingIntent, that is the identity under which you will actually be 741 * sending the Intent. The returned string is supplied by the system, so 742 * that an application can not spoof its package. 743 * 744 * <p class="note">Be careful about how you use this. All this tells you is 745 * who created the PendingIntent. It does <strong>not</strong> tell you who 746 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 747 * passed between applications, so the PendingIntent you receive from an application 748 * could actually be one it received from another application, meaning the result 749 * you get here will identify the original application. Because of this, you should 750 * only use this information to identify who you expect to be interacting with 751 * through a {@link #send} call, not who gave you the PendingIntent.</p> 752 * 753 * @return The package name of the PendingIntent, or null if there is 754 * none associated with it. 755 */ 756 public String getCreatorPackage() { 757 try { 758 return ActivityManagerNative.getDefault() 759 .getPackageForIntentSender(mTarget); 760 } catch (RemoteException e) { 761 // Should never happen. 762 return null; 763 } 764 } 765 766 /** 767 * Return the uid of the application that created this 768 * PendingIntent, that is the identity under which you will actually be 769 * sending the Intent. The returned integer is supplied by the system, so 770 * that an application can not spoof its uid. 771 * 772 * <p class="note">Be careful about how you use this. All this tells you is 773 * who created the PendingIntent. It does <strong>not</strong> tell you who 774 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 775 * passed between applications, so the PendingIntent you receive from an application 776 * could actually be one it received from another application, meaning the result 777 * you get here will identify the original application. Because of this, you should 778 * only use this information to identify who you expect to be interacting with 779 * through a {@link #send} call, not who gave you the PendingIntent.</p> 780 * 781 * @return The uid of the PendingIntent, or -1 if there is 782 * none associated with it. 783 */ 784 public int getCreatorUid() { 785 try { 786 return ActivityManagerNative.getDefault() 787 .getUidForIntentSender(mTarget); 788 } catch (RemoteException e) { 789 // Should never happen. 790 return -1; 791 } 792 } 793 794 /** 795 * Return the user handle of the application that created this 796 * PendingIntent, that is the user under which you will actually be 797 * sending the Intent. The returned UserHandle is supplied by the system, so 798 * that an application can not spoof its user. See 799 * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for 800 * more explanation of user handles. 801 * 802 * <p class="note">Be careful about how you use this. All this tells you is 803 * who created the PendingIntent. It does <strong>not</strong> tell you who 804 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 805 * passed between applications, so the PendingIntent you receive from an application 806 * could actually be one it received from another application, meaning the result 807 * you get here will identify the original application. Because of this, you should 808 * only use this information to identify who you expect to be interacting with 809 * through a {@link #send} call, not who gave you the PendingIntent.</p> 810 * 811 * @return The user handle of the PendingIntent, or null if there is 812 * none associated with it. 813 */ 814 public UserHandle getCreatorUserHandle() { 815 try { 816 int uid = ActivityManagerNative.getDefault() 817 .getUidForIntentSender(mTarget); 818 return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null; 819 } catch (RemoteException e) { 820 // Should never happen. 821 return null; 822 } 823 } 824 825 /** 826 * @hide 827 * Check to verify that this PendingIntent targets a specific package. 828 */ 829 public boolean isTargetedToPackage() { 830 try { 831 return ActivityManagerNative.getDefault() 832 .isIntentSenderTargetedToPackage(mTarget); 833 } catch (RemoteException e) { 834 // Should never happen. 835 return false; 836 } 837 } 838 839 /** 840 * @hide 841 * Check whether this PendingIntent will launch an Activity. 842 */ 843 public boolean isActivity() { 844 try { 845 return ActivityManagerNative.getDefault() 846 .isIntentSenderAnActivity(mTarget); 847 } catch (RemoteException e) { 848 // Should never happen. 849 return false; 850 } 851 } 852 853 /** 854 * @hide 855 * Return the Intent of this PendingIntent. 856 */ 857 public Intent getIntent() { 858 try { 859 return ActivityManagerNative.getDefault() 860 .getIntentForIntentSender(mTarget); 861 } catch (RemoteException e) { 862 // Should never happen. 863 return null; 864 } 865 } 866 867 /** 868 * Comparison operator on two PendingIntent objects, such that true 869 * is returned then they both represent the same operation from the 870 * same package. This allows you to use {@link #getActivity}, 871 * {@link #getBroadcast}, or {@link #getService} multiple times (even 872 * across a process being killed), resulting in different PendingIntent 873 * objects but whose equals() method identifies them as being the same 874 * operation. 875 */ 876 @Override 877 public boolean equals(Object otherObj) { 878 if (otherObj instanceof PendingIntent) { 879 return mTarget.asBinder().equals(((PendingIntent)otherObj) 880 .mTarget.asBinder()); 881 } 882 return false; 883 } 884 885 @Override 886 public int hashCode() { 887 return mTarget.asBinder().hashCode(); 888 } 889 890 @Override 891 public String toString() { 892 StringBuilder sb = new StringBuilder(128); 893 sb.append("PendingIntent{"); 894 sb.append(Integer.toHexString(System.identityHashCode(this))); 895 sb.append(": "); 896 sb.append(mTarget != null ? mTarget.asBinder() : null); 897 sb.append('}'); 898 return sb.toString(); 899 } 900 901 public int describeContents() { 902 return 0; 903 } 904 905 public void writeToParcel(Parcel out, int flags) { 906 out.writeStrongBinder(mTarget.asBinder()); 907 } 908 909 public static final Parcelable.Creator<PendingIntent> CREATOR 910 = new Parcelable.Creator<PendingIntent>() { 911 public PendingIntent createFromParcel(Parcel in) { 912 IBinder target = in.readStrongBinder(); 913 return target != null ? new PendingIntent(target) : null; 914 } 915 916 public PendingIntent[] newArray(int size) { 917 return new PendingIntent[size]; 918 } 919 }; 920 921 /** 922 * Convenience function for writing either a PendingIntent or null pointer to 923 * a Parcel. You must use this with {@link #readPendingIntentOrNullFromParcel} 924 * for later reading it. 925 * 926 * @param sender The PendingIntent to write, or null. 927 * @param out Where to write the PendingIntent. 928 */ 929 public static void writePendingIntentOrNullToParcel(PendingIntent sender, 930 Parcel out) { 931 out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() 932 : null); 933 } 934 935 /** 936 * Convenience function for reading either a Messenger or null pointer from 937 * a Parcel. You must have previously written the Messenger with 938 * {@link #writePendingIntentOrNullToParcel}. 939 * 940 * @param in The Parcel containing the written Messenger. 941 * 942 * @return Returns the Messenger read from the Parcel, or null if null had 943 * been written. 944 */ 945 public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) { 946 IBinder b = in.readStrongBinder(); 947 return b != null ? new PendingIntent(b) : null; 948 } 949 950 /*package*/ PendingIntent(IIntentSender target) { 951 mTarget = target; 952 } 953 954 /*package*/ PendingIntent(IBinder target) { 955 mTarget = IIntentSender.Stub.asInterface(target); 956 } 957 958 /** @hide */ 959 public IIntentSender getTarget() { 960 return mTarget; 961 } 962 } 963