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