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 { 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 * <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 */ getActivity(Context context, int requestCode, Intent intent, int flags)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 */ getActivity(Context context, int requestCode, Intent intent, int flags, Bundle options)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 */ getActivityAsUser(Context context, int requestCode, Intent intent, int flags, Bundle options, UserHandle user)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 */ getActivities(Context context, int requestCode, Intent[] intents, int flags)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 */ getActivities(Context context, int requestCode, Intent[] intents, int flags, Bundle options)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 */ getActivitiesAsUser(Context context, int requestCode, Intent[] intents, int flags, Bundle options, UserHandle user)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 */ getBroadcast(Context context, int requestCode, Intent intent, int flags)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 */ getBroadcastAsUser(Context context, int requestCode, Intent intent, int flags, UserHandle userHandle)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 */ getService(Context context, int requestCode, Intent intent, int flags)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 */ getIntentSender()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 */ cancel()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 */ send()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 */ send(int code)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 */ send(Context context, int code, Intent intent)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 */ send(int code, OnFinished onFinished, Handler handler)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 */ send(Context context, int code, Intent intent, OnFinished onFinished, Handler handler)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 */ send(Context context, int code, Intent intent, OnFinished onFinished, Handler handler, String requiredPermission)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 getTargetPackage()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 */ getCreatorPackage()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 */ getCreatorUid()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 */ getCreatorUserHandle()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 */ isTargetedToPackage()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 */ isActivity()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 */ getIntent()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 equals(Object otherObj)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 hashCode()880 public int hashCode() { 881 return mTarget.asBinder().hashCode(); 882 } 883 884 @Override toString()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 describeContents()895 public int describeContents() { 896 return 0; 897 } 898 writeToParcel(Parcel out, int flags)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 */ writePendingIntentOrNullToParcel(PendingIntent sender, Parcel out)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 */ readPendingIntentOrNullFromParcel(Parcel in)939 public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) { 940 IBinder b = in.readStrongBinder(); 941 return b != null ? new PendingIntent(b) : null; 942 } 943 PendingIntent(IIntentSender target)944 /*package*/ PendingIntent(IIntentSender target) { 945 mTarget = target; 946 } 947 PendingIntent(IBinder target)948 /*package*/ PendingIntent(IBinder target) { 949 mTarget = IIntentSender.Stub.asInterface(target); 950 } 951 952 /** @hide */ getTarget()953 public IIntentSender getTarget() { 954 return mTarget; 955 } 956 } 957