blob: 18d9b92fbc5cd90eb7c87f865f97dabe217f92c2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.app;
18
19import android.content.Context;
20import android.content.Intent;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070021import android.content.IIntentReceiver;
22import android.content.IIntentSender;
23import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.os.Bundle;
25import android.os.RemoteException;
26import android.os.Handler;
27import android.os.IBinder;
28import android.os.Parcel;
29import android.os.Parcelable;
30import android.util.AndroidException;
31
32/**
33 * A description of an Intent and target action to perform with it. Instances
34 * of this class are created with {@link #getActivity},
35 * {@link #getBroadcast}, {@link #getService}; the returned object can be
36 * handed to other applications so that they can perform the action you
37 * described on your behalf at a later time.
38 *
39 * <p>By giving a PendingIntent to another application,
40 * you are granting it the right to perform the operation you have specified
41 * as if the other application was yourself (with the same permissions and
42 * identity). As such, you should be careful about how you build the PendingIntent:
43 * often, for example, the base Intent you supply will have the component
44 * name explicitly set to one of your own components, to ensure it is ultimately
45 * sent there and nowhere else.
46 *
47 * <p>A PendingIntent itself is simply a reference to a token maintained by
48 * the system describing the original data used to retrieve it. This means
49 * that, even if its owning application's process is killed, the
50 * PendingIntent itself will remain usable from other processes that
51 * have been given it. If the creating application later re-retrieves the
52 * same kind of PendingIntent (same operation, same Intent action, data,
53 * categories, and components, and same flags), it will receive a PendingIntent
54 * representing the same token if that is still valid, and can thus call
55 * {@link #cancel} to remove it.
56 */
57public final class PendingIntent implements Parcelable {
58 private final IIntentSender mTarget;
59
60 /**
61 * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
62 * {@link #getService}: this
63 * PendingIntent can only be used once. If set, after
64 * {@link #send()} is called on it, it will be automatically
65 * canceled for you and any future attempt to send through it will fail.
66 */
67 public static final int FLAG_ONE_SHOT = 1<<30;
68 /**
69 * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
70 * {@link #getService}: if the described PendingIntent does not already
71 * exist, then simply return null instead of creating it.
72 */
73 public static final int FLAG_NO_CREATE = 1<<29;
74 /**
75 * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
76 * {@link #getService}: if the described PendingIntent already exists,
77 * the current one is canceled before generating a new one. You can use
78 * this to retrieve a new PendingIntent when you are only changing the
79 * extra data in the Intent; by canceling the previous pending intent,
80 * this ensures that only entities given the new data will be able to
81 * launch it. If this assurance is not an issue, consider
82 * {@link #FLAG_UPDATE_CURRENT}.
83 */
84 public static final int FLAG_CANCEL_CURRENT = 1<<28;
85 /**
86 * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
87 * {@link #getService}: if the described PendingIntent already exists,
88 * then keep it but its replace its extra data with what is in this new
89 * Intent. This can be used if you are creating intents where only the
90 * extras change, and don't care that any entities that received your
91 * previous PendingIntent will be able to launch it with your new
92 * extras even if they are not explicitly given to it.
93 */
94 public static final int FLAG_UPDATE_CURRENT = 1<<27;
95
96 /**
97 * Exception thrown when trying to send through a PendingIntent that
98 * has been canceled or is otherwise no longer able to execute the request.
99 */
100 public static class CanceledException extends AndroidException {
101 public CanceledException() {
102 }
103
104 public CanceledException(String name) {
105 super(name);
106 }
107
108 public CanceledException(Exception cause) {
109 super(cause);
110 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
113 /**
114 * Callback interface for discovering when a send operation has
115 * completed. Primarily for use with a PendingIntent that is
116 * performing a broadcast, this provides the same information as
117 * calling {@link Context#sendOrderedBroadcast(Intent, String,
118 * android.content.BroadcastReceiver, Handler, int, String, Bundle)
119 * Context.sendBroadcast()} with a final BroadcastReceiver.
120 */
121 public interface OnFinished {
122 /**
123 * Called when a send operation as completed.
124 *
125 * @param pendingIntent The PendingIntent this operation was sent through.
126 * @param intent The original Intent that was sent.
127 * @param resultCode The final result code determined by the send.
128 * @param resultData The final data collected by a broadcast.
129 * @param resultExtras The final extras collected by a broadcast.
130 */
131 void onSendFinished(PendingIntent pendingIntent, Intent intent,
132 int resultCode, String resultData, Bundle resultExtras);
133 }
134
135 private static class FinishedDispatcher extends IIntentReceiver.Stub
136 implements Runnable {
137 private final PendingIntent mPendingIntent;
138 private final OnFinished mWho;
139 private final Handler mHandler;
140 private Intent mIntent;
141 private int mResultCode;
142 private String mResultData;
143 private Bundle mResultExtras;
144 FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) {
145 mPendingIntent = pi;
146 mWho = who;
147 mHandler = handler;
148 }
149 public void performReceive(Intent intent, int resultCode,
150 String data, Bundle extras, boolean serialized) {
151 mIntent = intent;
152 mResultCode = resultCode;
153 mResultData = data;
154 mResultExtras = extras;
155 if (mHandler == null) {
156 run();
157 } else {
158 mHandler.post(this);
159 }
160 }
161 public void run() {
162 mWho.onSendFinished(mPendingIntent, mIntent, mResultCode,
163 mResultData, mResultExtras);
164 }
165 }
166
167 /**
168 * Retrieve a PendingIntent that will start a new activity, like calling
169 * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
170 * Note that the activity will be started outside of the context of an
171 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
172 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
173 *
174 * @param context The Context in which this PendingIntent should start
175 * the activity.
176 * @param requestCode Private request code for the sender (currently
177 * not used).
178 * @param intent Intent of the activity to be launched.
179 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
180 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
181 * or any of the flags as supported by
182 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
183 * of the intent that can be supplied when the actual send happens.
184 *
185 * @return Returns an existing or new PendingIntent matching the given
186 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been
187 * supplied.
188 */
189 public static PendingIntent getActivity(Context context, int requestCode,
190 Intent intent, int flags) {
191 String packageName = context.getPackageName();
192 String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
193 context.getContentResolver()) : null;
194 try {
195 IIntentSender target =
196 ActivityManagerNative.getDefault().getIntentSender(
197 IActivityManager.INTENT_SENDER_ACTIVITY, packageName,
198 null, null, requestCode, intent, resolvedType, flags);
199 return target != null ? new PendingIntent(target) : null;
200 } catch (RemoteException e) {
201 }
202 return null;
203 }
204
205 /**
206 * Retrieve a PendingIntent that will perform a broadcast, like calling
207 * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
208 *
209 * @param context The Context in which this PendingIntent should perform
210 * the broadcast.
211 * @param requestCode Private request code for the sender (currently
212 * not used).
213 * @param intent The Intent to be broadcast.
214 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
215 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
216 * or any of the flags as supported by
217 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
218 * of the intent that can be supplied when the actual send happens.
219 *
220 * @return Returns an existing or new PendingIntent matching the given
221 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been
222 * supplied.
223 */
224 public static PendingIntent getBroadcast(Context context, int requestCode,
225 Intent intent, int flags) {
226 String packageName = context.getPackageName();
227 String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
228 context.getContentResolver()) : null;
229 try {
230 IIntentSender target =
231 ActivityManagerNative.getDefault().getIntentSender(
232 IActivityManager.INTENT_SENDER_BROADCAST, packageName,
233 null, null, requestCode, intent, resolvedType, flags);
234 return target != null ? new PendingIntent(target) : null;
235 } catch (RemoteException e) {
236 }
237 return null;
238 }
239
240 /**
241 * Retrieve a PendingIntent that will start a service, like calling
242 * {@link Context#startService Context.startService()}. The start
243 * arguments given to the service will come from the extras of the Intent.
244 *
245 * @param context The Context in which this PendingIntent should start
246 * the service.
247 * @param requestCode Private request code for the sender (currently
248 * not used).
249 * @param intent An Intent describing the service to be started.
250 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
251 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
252 * or any of the flags as supported by
253 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
254 * of the intent that can be supplied when the actual send happens.
255 *
256 * @return Returns an existing or new PendingIntent matching the given
257 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been
258 * supplied.
259 */
260 public static PendingIntent getService(Context context, int requestCode,
261 Intent intent, int flags) {
262 String packageName = context.getPackageName();
263 String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
264 context.getContentResolver()) : null;
265 try {
266 IIntentSender target =
267 ActivityManagerNative.getDefault().getIntentSender(
268 IActivityManager.INTENT_SENDER_SERVICE, packageName,
269 null, null, requestCode, intent, resolvedType, flags);
270 return target != null ? new PendingIntent(target) : null;
271 } catch (RemoteException e) {
272 }
273 return null;
274 }
275
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700276 /**
277 * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent
278 *
279 * @return Returns a IntentSender object that wraps the sender of PendingIntent
280 *
281 */
282 public IntentSender getIntentSender() {
Dianne Hackborn7f205432009-07-28 00:13:47 -0700283 return new IntentSender(mTarget);
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700284 }
285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 /**
287 * Cancel a currently active PendingIntent. Only the original application
288 * owning an PendingIntent can cancel it.
289 */
290 public void cancel() {
291 try {
292 ActivityManagerNative.getDefault().cancelIntentSender(mTarget);
293 } catch (RemoteException e) {
294 }
295 }
296
297 /**
298 * Perform the operation associated with this PendingIntent.
299 *
300 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
301 *
302 * @throws CanceledException Throws CanceledException if the PendingIntent
303 * is no longer allowing more intents to be sent through it.
304 */
305 public void send() throws CanceledException {
306 send(null, 0, null, null, null);
307 }
308
309 /**
310 * Perform the operation associated with this PendingIntent.
311 *
312 * @param code Result code to supply back to the PendingIntent's target.
313 *
314 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
315 *
316 * @throws CanceledException Throws CanceledException if the PendingIntent
317 * is no longer allowing more intents to be sent through it.
318 */
319 public void send(int code) throws CanceledException {
320 send(null, code, null, null, null);
321 }
322
323 /**
324 * Perform the operation associated with this PendingIntent, allowing the
325 * caller to specify information about the Intent to use.
326 *
327 * @param context The Context of the caller.
328 * @param code Result code to supply back to the PendingIntent's target.
329 * @param intent Additional Intent data. See {@link Intent#fillIn
330 * Intent.fillIn()} for information on how this is applied to the
331 * original Intent.
332 *
333 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
334 *
335 * @throws CanceledException Throws CanceledException if the PendingIntent
336 * is no longer allowing more intents to be sent through it.
337 */
338 public void send(Context context, int code, Intent intent)
339 throws CanceledException {
340 send(context, code, intent, null, null);
341 }
342
343 /**
344 * Perform the operation associated with this PendingIntent, allowing the
345 * caller to be notified when the send has completed.
346 *
347 * @param code Result code to supply back to the PendingIntent's target.
348 * @param onFinished The object to call back on when the send has
349 * completed, or null for no callback.
350 * @param handler Handler identifying the thread on which the callback
351 * should happen. If null, the callback will happen from the thread
352 * pool of the process.
353 *
354 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
355 *
356 * @throws CanceledException Throws CanceledException if the PendingIntent
357 * is no longer allowing more intents to be sent through it.
358 */
359 public void send(int code, OnFinished onFinished, Handler handler)
360 throws CanceledException {
361 send(null, code, null, onFinished, handler);
362 }
363
364 /**
365 * Perform the operation associated with this PendingIntent, allowing the
366 * caller to specify information about the Intent to use and be notified
367 * when the send has completed.
368 *
369 * <p>For the intent parameter, a PendingIntent
370 * often has restrictions on which fields can be supplied here, based on
371 * how the PendingIntent was retrieved in {@link #getActivity},
372 * {@link #getBroadcast}, or {@link #getService}.
373 *
374 * @param context The Context of the caller. This may be null if
375 * <var>intent</var> is also null.
376 * @param code Result code to supply back to the PendingIntent's target.
377 * @param intent Additional Intent data. See {@link Intent#fillIn
378 * Intent.fillIn()} for information on how this is applied to the
379 * original Intent. Use null to not modify the original Intent.
380 * @param onFinished The object to call back on when the send has
381 * completed, or null for no callback.
382 * @param handler Handler identifying the thread on which the callback
383 * should happen. If null, the callback will happen from the thread
384 * pool of the process.
385 *
386 * @see #send()
387 * @see #send(int)
388 * @see #send(Context, int, Intent)
389 * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
390 *
391 * @throws CanceledException Throws CanceledException if the PendingIntent
392 * is no longer allowing more intents to be sent through it.
393 */
394 public void send(Context context, int code, Intent intent,
395 OnFinished onFinished, Handler handler) throws CanceledException {
396 try {
397 String resolvedType = intent != null ?
398 intent.resolveTypeIfNeeded(context.getContentResolver())
399 : null;
400 int res = mTarget.send(code, intent, resolvedType,
401 onFinished != null
402 ? new FinishedDispatcher(this, onFinished, handler)
403 : null);
404 if (res < 0) {
405 throw new CanceledException();
406 }
407 } catch (RemoteException e) {
408 throw new CanceledException(e);
409 }
410 }
411
412 /**
413 * Return the package name of the application that created this
414 * PendingIntent, that is the identity under which you will actually be
415 * sending the Intent. The returned string is supplied by the system, so
416 * that an application can not spoof its package.
417 *
418 * @return The package name of the PendingIntent, or null if there is
419 * none associated with it.
420 */
421 public String getTargetPackage() {
422 try {
423 return ActivityManagerNative.getDefault()
424 .getPackageForIntentSender(mTarget);
425 } catch (RemoteException e) {
426 // Should never happen.
427 return null;
428 }
429 }
430
431 /**
432 * Comparison operator on two PendingIntent objects, such that true
433 * is returned then they both represent the same operation from the
434 * same package. This allows you to use {@link #getActivity},
435 * {@link #getBroadcast}, or {@link #getService} multiple times (even
436 * across a process being killed), resulting in different PendingIntent
437 * objects but whose equals() method identifies them as being the same
438 * operation.
439 */
440 @Override
441 public boolean equals(Object otherObj) {
442 if (otherObj instanceof PendingIntent) {
443 return mTarget.asBinder().equals(((PendingIntent)otherObj)
444 .mTarget.asBinder());
445 }
446 return false;
447 }
448
449 @Override
450 public int hashCode() {
451 return mTarget.asBinder().hashCode();
452 }
453
454 @Override
455 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700456 StringBuilder sb = new StringBuilder(128);
457 sb.append("PendingIntent{");
458 sb.append(Integer.toHexString(System.identityHashCode(this)));
459 sb.append(": ");
460 sb.append(mTarget != null ? mTarget.asBinder() : null);
461 sb.append('}');
462 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 }
464
465 public int describeContents() {
466 return 0;
467 }
468
469 public void writeToParcel(Parcel out, int flags) {
470 out.writeStrongBinder(mTarget.asBinder());
471 }
472
473 public static final Parcelable.Creator<PendingIntent> CREATOR
474 = new Parcelable.Creator<PendingIntent>() {
475 public PendingIntent createFromParcel(Parcel in) {
476 IBinder target = in.readStrongBinder();
477 return target != null ? new PendingIntent(target) : null;
478 }
479
480 public PendingIntent[] newArray(int size) {
481 return new PendingIntent[size];
482 }
483 };
484
485 /**
486 * Convenience function for writing either a PendingIntent or null pointer to
487 * a Parcel. You must use this with {@link #readPendingIntentOrNullFromParcel}
488 * for later reading it.
489 *
490 * @param sender The PendingIntent to write, or null.
491 * @param out Where to write the PendingIntent.
492 */
493 public static void writePendingIntentOrNullToParcel(PendingIntent sender,
494 Parcel out) {
495 out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
496 : null);
497 }
498
499 /**
500 * Convenience function for reading either a Messenger or null pointer from
501 * a Parcel. You must have previously written the Messenger with
502 * {@link #writePendingIntentOrNullToParcel}.
503 *
504 * @param in The Parcel containing the written Messenger.
505 *
506 * @return Returns the Messenger read from the Parcel, or null if null had
507 * been written.
508 */
509 public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) {
510 IBinder b = in.readStrongBinder();
511 return b != null ? new PendingIntent(b) : null;
512 }
513
514 /*package*/ PendingIntent(IIntentSender target) {
515 mTarget = target;
516 }
517
518 /*package*/ PendingIntent(IBinder target) {
519 mTarget = IIntentSender.Stub.asInterface(target);
520 }
521
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700522 /** @hide */
523 public IIntentSender getTarget() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 return mTarget;
525 }
526}