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