blob: d71a8d6f73a1f37a5d195fcb13ff4449e08ff924 [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.content;
18
19import android.app.ActivityManagerNative;
Dianne Hackborne829fef2010-10-26 17:44:01 -070020import android.app.ActivityThread;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.app.IActivityManager;
Dianne Hackborne829fef2010-10-26 17:44:01 -070022import android.app.QueuedWork;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.os.Bundle;
24import android.os.IBinder;
25import android.os.RemoteException;
26import android.util.Log;
Dianne Hackborne829fef2010-10-26 17:44:01 -070027import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
29/**
30 * Base class for code that will receive intents sent by sendBroadcast().
31 * You can either dynamically register an instance of this class with
32 * {@link Context#registerReceiver Context.registerReceiver()}
33 * or statically publish an implementation through the
34 * {@link android.R.styleable#AndroidManifestReceiver <receiver>}
35 * tag in your <code>AndroidManifest.xml</code>. <em><strong>Note:</strong></em>
36 * &nbsp;&nbsp;&nbsp;If registering a receiver in your
37 * {@link android.app.Activity#onResume() Activity.onResume()}
38 * implementation, you should unregister it in
39 * {@link android.app.Activity#onPause() Activity.onPause()}.
40 * (You won't receive intents when paused,
41 * and this will cut down on unnecessary system overhead). Do not unregister in
42 * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()},
43 * because this won't be called if the user moves back in the history
44 * stack.
45 *
46 * <p>There are two major classes of broadcasts that can be received:</p>
47 * <ul>
48 * <li> <b>Normal broadcasts</b> (sent with {@link Context#sendBroadcast(Intent)
49 * Context.sendBroadcast}) are completely asynchronous. All receivers of the
Chris Tatea34df8a22009-04-02 23:15:58 -070050 * broadcast are run in an undefined order, often at the same time. This is
51 * more efficient, but means that receivers cannot use the result or abort
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 * APIs included here.
53 * <li> <b>Ordered broadcasts</b> (sent with {@link Context#sendOrderedBroadcast(Intent, String)
54 * Context.sendOrderedBroadcast}) are delivered to one receiver at a time.
55 * As each receiver executes in turn, it can propagate a result to the next
56 * receiver, or it can completely abort the broadcast so that it won't be passed
Chris Tatea34df8a22009-04-02 23:15:58 -070057 * to other receivers. The order receivers run in can be controlled with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 * {@link android.R.styleable#AndroidManifestIntentFilter_priority
59 * android:priority} attribute of the matching intent-filter; receivers with
60 * the same priority will be run in an arbitrary order.
61 * </ul>
62 *
63 * <p>Even in the case of normal broadcasts, the system may in some
64 * situations revert to delivering the broadcast one receiver at a time. In
65 * particular, for receivers that may require the creation of a process, only
66 * one will be run at a time to avoid overloading the system with new processes.
Chris Tatea34df8a22009-04-02 23:15:58 -070067 * In this situation, however, the non-ordered semantics hold: these receivers still
68 * cannot return results or abort their broadcast.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 *
70 * <p>Note that, although the Intent class is used for sending and receiving
71 * these broadcasts, the Intent broadcast mechanism here is completely separate
72 * from Intents that are used to start Activities with
73 * {@link Context#startActivity Context.startActivity()}.
The Android Open Source Project10592532009-03-18 17:39:46 -070074 * There is no way for a BroadcastReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 * to see or capture Intents used with startActivity(); likewise, when
76 * you broadcast an Intent, you will never find or start an Activity.
77 * These two operations are semantically very different: starting an
78 * Activity with an Intent is a foreground operation that modifies what the
79 * user is currently interacting with; broadcasting an Intent is a background
80 * operation that the user is not normally aware of.
81 *
82 * <p>The BroadcastReceiver class (when launched as a component through
83 * a manifest's {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
84 * tag) is an important part of an
85 * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">application's overall lifecycle</a>.</p>
86 *
87 * <p>Topics covered here:
88 * <ol>
89 * <li><a href="#ReceiverLifecycle">Receiver Lifecycle</a>
90 * <li><a href="#Permissions">Permissions</a>
91 * <li><a href="#ProcessLifecycle">Process Lifecycle</a>
92 * </ol>
Joe Fernandezb54e7a32011-10-03 15:09:50 -070093 *
94 * <div class="special reference">
95 * <h3>Developer Guides</h3>
96 * <p>For information about how to use this class to receive and resolve intents, read the
97 * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
98 * developer guide.</p>
99 * </div>
100 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 * <a name="ReceiverLifecycle"></a>
102 * <h3>Receiver Lifecycle</h3>
103 *
104 * <p>A BroadcastReceiver object is only valid for the duration of the call
105 * to {@link #onReceive}. Once your code returns from this function,
106 * the system considers the object to be finished and no longer active.
107 *
108 * <p>This has important repercussions to what you can do in an
109 * {@link #onReceive} implementation: anything that requires asynchronous
110 * operation is not available, because you will need to return from the
111 * function to handle the asynchronous operation, but at that point the
112 * BroadcastReceiver is no longer active and thus the system is free to kill
113 * its process before the asynchronous operation completes.
114 *
115 * <p>In particular, you may <i>not</i> show a dialog or bind to a service from
The Android Open Source Project10592532009-03-18 17:39:46 -0700116 * within a BroadcastReceiver. For the former, you should instead use the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 * {@link android.app.NotificationManager} API. For the latter, you can
118 * use {@link android.content.Context#startService Context.startService()} to
119 * send a command to the service.
120 *
121 * <a name="Permissions"></a>
122 * <h3>Permissions</h3>
123 *
124 * <p>Access permissions can be enforced by either the sender or receiver
125 * of an Intent.
126 *
127 * <p>To enforce a permission when sending, you supply a non-null
128 * <var>permission</var> argument to
129 * {@link Context#sendBroadcast(Intent, String)} or
130 * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}.
131 * Only receivers who have been granted this permission
132 * (by requesting it with the
133 * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
134 * tag in their <code>AndroidManifest.xml</code>) will be able to receive
135 * the broadcast.
136 *
137 * <p>To enforce a permission when receiving, you supply a non-null
138 * <var>permission</var> when registering your receiver -- either when calling
139 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)}
140 * or in the static
141 * {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
142 * tag in your <code>AndroidManifest.xml</code>. Only broadcasters who have
143 * been granted this permission (by requesting it with the
144 * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
145 * tag in their <code>AndroidManifest.xml</code>) will be able to send an
146 * Intent to the receiver.
147 *
148 * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
149 * document for more information on permissions and security in general.
150 *
151 * <a name="ProcessLifecycle"></a>
152 * <h3>Process Lifecycle</h3>
153 *
The Android Open Source Project10592532009-03-18 17:39:46 -0700154 * <p>A process that is currently executing a BroadcastReceiver (that is,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 * currently running the code in its {@link #onReceive} method) is
156 * considered to be a foreground process and will be kept running by the
157 * system except under cases of extreme memory pressure.
158 *
159 * <p>Once you return from onReceive(), the BroadcastReceiver is no longer
160 * active, and its hosting process is only as important as any other application
161 * components that are running in it. This is especially important because if
162 * that process was only hosting the BroadcastReceiver (a common case for
163 * applications that the user has never or not recently interacted with), then
164 * upon returning from onReceive() the system will consider its process
165 * to be empty and aggressively kill it so that resources are available for other
166 * more important processes.
167 *
168 * <p>This means that for longer-running operations you will often use
Chris Tatea34df8a22009-04-02 23:15:58 -0700169 * a {@link android.app.Service} in conjunction with a BroadcastReceiver to keep
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 * the containing process active for the entire time of your operation.
171 */
172public abstract class BroadcastReceiver {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700173 private PendingResult mPendingResult;
174 private boolean mDebugUnregister;
175
176 /**
177 * State for a result that is pending for a broadcast receiver. Returned
178 * by {@link BroadcastReceiver#goAsync() goAsync()}
179 * while in {@link BroadcastReceiver#onReceive BroadcastReceiver.onReceive()}.
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800180 * This allows you to return from onReceive() without having the broadcast
181 * terminate; you must call {@link #finish()} once you are done with the
182 * broadcast. This allows you to process the broadcast off of the main
183 * thread of your app.
184 *
185 * <p>Note on threading: the state inside of this class is not itself
186 * thread-safe, however you can use it from any thread if you properly
187 * sure that you do not have races. Typically this means you will hand
188 * the entire object to another thread, which will be solely responsible
189 * for setting any results and finally calling {@link #finish()}.
Dianne Hackborne829fef2010-10-26 17:44:01 -0700190 */
191 public static class PendingResult {
192 /** @hide */
193 public static final int TYPE_COMPONENT = 0;
194 /** @hide */
195 public static final int TYPE_REGISTERED = 1;
196 /** @hide */
197 public static final int TYPE_UNREGISTERED = 2;
198
199 final int mType;
200 final boolean mOrderedHint;
201 final boolean mInitialStickyHint;
202 final IBinder mToken;
203
204 int mResultCode;
205 String mResultData;
206 Bundle mResultExtras;
207 boolean mAbortBroadcast;
208 boolean mFinished;
209
210 /** @hide */
211 public PendingResult(int resultCode, String resultData, Bundle resultExtras,
212 int type, boolean ordered, boolean sticky, IBinder token) {
213 mResultCode = resultCode;
214 mResultData = resultData;
215 mResultExtras = resultExtras;
216 mType = type;
217 mOrderedHint = ordered;
218 mInitialStickyHint = sticky;
219 mToken = token;
220 }
221
222 /**
223 * Version of {@link BroadcastReceiver#setResultCode(int)
224 * BroadcastReceiver.setResultCode(int)} for
225 * asynchronous broadcast handling.
226 */
227 public final void setResultCode(int code) {
228 checkSynchronousHint();
229 mResultCode = code;
230 }
231
232 /**
233 * Version of {@link BroadcastReceiver#getResultCode()
234 * BroadcastReceiver.getResultCode()} for
235 * asynchronous broadcast handling.
236 */
237 public final int getResultCode() {
238 return mResultCode;
239 }
240
241 /**
242 * Version of {@link BroadcastReceiver#setResultData(String)
243 * BroadcastReceiver.setResultData(String)} for
244 * asynchronous broadcast handling.
245 */
246 public final void setResultData(String data) {
247 checkSynchronousHint();
248 mResultData = data;
249 }
250
251 /**
252 * Version of {@link BroadcastReceiver#getResultData()
253 * BroadcastReceiver.getResultData()} for
254 * asynchronous broadcast handling.
255 */
256 public final String getResultData() {
257 return mResultData;
258 }
259
260 /**
261 * Version of {@link BroadcastReceiver#setResultExtras(Bundle)
262 * BroadcastReceiver.setResultExtras(Bundle)} for
263 * asynchronous broadcast handling.
264 */
265 public final void setResultExtras(Bundle extras) {
266 checkSynchronousHint();
267 mResultExtras = extras;
268 }
269
270 /**
271 * Version of {@link BroadcastReceiver#getResultExtras(boolean)
272 * BroadcastReceiver.getResultExtras(boolean)} for
273 * asynchronous broadcast handling.
274 */
275 public final Bundle getResultExtras(boolean makeMap) {
276 Bundle e = mResultExtras;
277 if (!makeMap) return e;
278 if (e == null) mResultExtras = e = new Bundle();
279 return e;
280 }
281
282 /**
283 * Version of {@link BroadcastReceiver#setResult(int, String, Bundle)
284 * BroadcastReceiver.setResult(int, String, Bundle)} for
285 * asynchronous broadcast handling.
286 */
287 public final void setResult(int code, String data, Bundle extras) {
288 checkSynchronousHint();
289 mResultCode = code;
290 mResultData = data;
291 mResultExtras = extras;
292 }
293
294 /**
295 * Version of {@link BroadcastReceiver#getAbortBroadcast()
296 * BroadcastReceiver.getAbortBroadcast()} for
297 * asynchronous broadcast handling.
298 */
299 public final boolean getAbortBroadcast() {
300 return mAbortBroadcast;
301 }
302
303 /**
304 * Version of {@link BroadcastReceiver#abortBroadcast()
305 * BroadcastReceiver.abortBroadcast()} for
306 * asynchronous broadcast handling.
307 */
308 public final void abortBroadcast() {
309 checkSynchronousHint();
310 mAbortBroadcast = true;
311 }
312
313 /**
314 * Version of {@link BroadcastReceiver#clearAbortBroadcast()
315 * BroadcastReceiver.clearAbortBroadcast()} for
316 * asynchronous broadcast handling.
317 */
318 public final void clearAbortBroadcast() {
319 mAbortBroadcast = false;
320 }
321
322 /**
323 * Finish the broadcast. The current result will be sent and the
324 * next broadcast will proceed.
325 */
326 public final void finish() {
327 if (mType == TYPE_COMPONENT) {
328 final IActivityManager mgr = ActivityManagerNative.getDefault();
329 if (QueuedWork.hasPendingWork()) {
330 // If this is a broadcast component, we need to make sure any
331 // queued work is complete before telling AM we are done, so
332 // we don't have our process killed before that. We now know
333 // there is pending work; put another piece of work at the end
334 // of the list to finish the broadcast, so we don't block this
335 // thread (which may be the main thread) to have it finished.
336 //
337 // Note that we don't need to use QueuedWork.add() with the
338 // runnable, since we know the AM is waiting for us until the
339 // executor gets to it.
340 QueuedWork.singleThreadExecutor().execute( new Runnable() {
341 @Override public void run() {
342 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
343 "Finishing broadcast after work to component " + mToken);
344 sendFinished(mgr);
345 }
346 });
347 } else {
348 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
349 "Finishing broadcast to component " + mToken);
350 sendFinished(mgr);
351 }
352 } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
353 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
354 "Finishing broadcast to " + mToken);
355 final IActivityManager mgr = ActivityManagerNative.getDefault();
356 sendFinished(mgr);
357 }
358 }
359
360 /** @hide */
361 public void setExtrasClassLoader(ClassLoader cl) {
362 if (mResultExtras != null) {
363 mResultExtras.setClassLoader(cl);
364 }
365 }
366
367 /** @hide */
368 public void sendFinished(IActivityManager am) {
369 synchronized (this) {
370 if (mFinished) {
371 throw new IllegalStateException("Broadcast already finished");
372 }
373 mFinished = true;
374
375 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400376 if (mResultExtras != null) {
377 mResultExtras.setAllowFds(false);
378 }
Dianne Hackborne829fef2010-10-26 17:44:01 -0700379 if (mOrderedHint) {
380 am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
381 mAbortBroadcast);
382 } else {
383 // This broadcast was sent to a component; it is not ordered,
384 // but we still need to tell the activity manager we are done.
385 am.finishReceiver(mToken, 0, null, null, false);
386 }
387 } catch (RemoteException ex) {
388 }
389 }
390 }
391
392 void checkSynchronousHint() {
393 // Note that we don't assert when receiving the initial sticky value,
394 // since that may have come from an ordered broadcast. We'll catch
395 // them later when the real broadcast happens again.
396 if (mOrderedHint || mInitialStickyHint) {
397 return;
398 }
399 RuntimeException e = new RuntimeException(
400 "BroadcastReceiver trying to return result during a non-ordered broadcast");
401 e.fillInStackTrace();
402 Log.e("BroadcastReceiver", e.getMessage(), e);
403 }
404 }
405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 public BroadcastReceiver() {
407 }
408
409 /**
410 * This method is called when the BroadcastReceiver is receiving an Intent
411 * broadcast. During this time you can use the other methods on
412 * BroadcastReceiver to view/modify the current result values. The function
Chris Tatea34df8a22009-04-02 23:15:58 -0700413 * is normally called within the main thread of its process, so you should
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * never perform long-running operations in it (there is a timeout of
415 * 10 seconds that the system allows before considering the receiver to
416 * be blocked and a candidate to be killed). You cannot launch a popup dialog
417 * in your implementation of onReceive().
418 *
419 * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
420 * then the object is no longer alive after returning from this
421 * function.</b> This means you should not perform any operations that
422 * return a result to you asynchronously -- in particular, for interacting
423 * with services, you should use
424 * {@link Context#startService(Intent)} instead of
425 * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish
426 * to interact with a service that is already running, you can use
427 * {@link #peekService}.
428 *
Chris Tatea34df8a22009-04-02 23:15:58 -0700429 * <p>The Intent filters used in {@link android.content.Context#registerReceiver}
430 * and in application manifests are <em>not</em> guaranteed to be exclusive. They
431 * are hints to the operating system about how to find suitable recipients. It is
432 * possible for senders to force delivery to specific recipients, bypassing filter
433 * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()}
434 * implementations should respond only to known actions, ignoring any unexpected
435 * Intents that they may receive.
436 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * @param context The Context in which the receiver is running.
438 * @param intent The Intent being received.
439 */
440 public abstract void onReceive(Context context, Intent intent);
441
442 /**
Dianne Hackborne829fef2010-10-26 17:44:01 -0700443 * This can be called by an application in {@link #onReceive} to allow
444 * it to keep the broadcast active after returning from that function.
445 * This does <em>not</em> change the expectation of being relatively
446 * responsive to the broadcast (finishing it within 10s), but does allow
447 * the implementation to move work related to it over to another thread
448 * to avoid glitching the main UI thread due to disk IO.
449 *
450 * @return Returns a {@link PendingResult} representing the result of
451 * the active broadcast. The BroadcastRecord itself is no longer active;
452 * all data and other interaction must go through {@link PendingResult}
453 * APIs. The {@link PendingResult#finish PendingResult.finish()} method
454 * must be called once processing of the broadcast is done.
455 */
456 public final PendingResult goAsync() {
457 PendingResult res = mPendingResult;
458 mPendingResult = null;
459 return res;
460 }
461
462 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 * Provide a binder to an already-running service. This method is synchronous
464 * and will not start the target service if it is not present, so it is safe
465 * to call from {@link #onReceive}.
466 *
467 * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
468 * @param service The Intent indicating the service you wish to use. See {@link
469 * Context#startService(Intent)} for more information.
470 */
471 public IBinder peekService(Context myContext, Intent service) {
472 IActivityManager am = ActivityManagerNative.getDefault();
473 IBinder binder = null;
474 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400475 service.setAllowFds(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 binder = am.peekService(service, service.resolveTypeIfNeeded(
477 myContext.getContentResolver()));
478 } catch (RemoteException e) {
479 }
480 return binder;
481 }
482
483 /**
484 * Change the current result code of this broadcast; only works with
485 * broadcasts sent through
486 * {@link Context#sendOrderedBroadcast(Intent, String)
487 * Context.sendOrderedBroadcast}. Often uses the
488 * Activity {@link android.app.Activity#RESULT_CANCELED} and
489 * {@link android.app.Activity#RESULT_OK} constants, though the
490 * actual meaning of this value is ultimately up to the broadcaster.
491 *
Dianne Hackborne829fef2010-10-26 17:44:01 -0700492 * <p class="note">This method does not work with non-ordered broadcasts such
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 * as those sent with {@link Context#sendBroadcast(Intent)
Dianne Hackborne829fef2010-10-26 17:44:01 -0700494 * Context.sendBroadcast}</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 *
496 * @param code The new result code.
497 *
498 * @see #setResult(int, String, Bundle)
499 */
500 public final void setResultCode(int code) {
501 checkSynchronousHint();
Dianne Hackborne829fef2010-10-26 17:44:01 -0700502 mPendingResult.mResultCode = code;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 }
504
505 /**
506 * Retrieve the current result code, as set by the previous receiver.
507 *
508 * @return int The current result code.
509 */
510 public final int getResultCode() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700511 return mPendingResult != null ? mPendingResult.mResultCode : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 }
513
514 /**
515 * Change the current result data of this broadcast; only works with
516 * broadcasts sent through
517 * {@link Context#sendOrderedBroadcast(Intent, String)
518 * Context.sendOrderedBroadcast}. This is an arbitrary
519 * string whose interpretation is up to the broadcaster.
520 *
521 * <p><strong>This method does not work with non-ordered broadcasts such
522 * as those sent with {@link Context#sendBroadcast(Intent)
523 * Context.sendBroadcast}</strong></p>
524 *
525 * @param data The new result data; may be null.
526 *
527 * @see #setResult(int, String, Bundle)
528 */
529 public final void setResultData(String data) {
530 checkSynchronousHint();
Dianne Hackborne829fef2010-10-26 17:44:01 -0700531 mPendingResult.mResultData = data;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 }
533
534 /**
535 * Retrieve the current result data, as set by the previous receiver.
536 * Often this is null.
537 *
538 * @return String The current result data; may be null.
539 */
540 public final String getResultData() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700541 return mPendingResult != null ? mPendingResult.mResultData : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 }
543
544 /**
545 * Change the current result extras of this broadcast; only works with
546 * broadcasts sent through
547 * {@link Context#sendOrderedBroadcast(Intent, String)
548 * Context.sendOrderedBroadcast}. This is a Bundle
549 * holding arbitrary data, whose interpretation is up to the
550 * broadcaster. Can be set to null. Calling this method completely
551 * replaces the current map (if any).
552 *
553 * <p><strong>This method does not work with non-ordered broadcasts such
554 * as those sent with {@link Context#sendBroadcast(Intent)
555 * Context.sendBroadcast}</strong></p>
556 *
557 * @param extras The new extra data map; may be null.
558 *
559 * @see #setResult(int, String, Bundle)
560 */
561 public final void setResultExtras(Bundle extras) {
562 checkSynchronousHint();
Dianne Hackborne829fef2010-10-26 17:44:01 -0700563 mPendingResult.mResultExtras = extras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 }
565
566 /**
567 * Retrieve the current result extra data, as set by the previous receiver.
568 * Any changes you make to the returned Map will be propagated to the next
569 * receiver.
570 *
571 * @param makeMap If true then a new empty Map will be made for you if the
572 * current Map is null; if false you should be prepared to
573 * receive a null Map.
574 *
575 * @return Map The current extras map.
576 */
577 public final Bundle getResultExtras(boolean makeMap) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700578 if (mPendingResult == null) {
579 return null;
580 }
581 Bundle e = mPendingResult.mResultExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 if (!makeMap) return e;
Dianne Hackborne829fef2010-10-26 17:44:01 -0700583 if (e == null) mPendingResult.mResultExtras = e = new Bundle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 return e;
585 }
586
587 /**
588 * Change all of the result data returned from this broadcasts; only works
589 * with broadcasts sent through
590 * {@link Context#sendOrderedBroadcast(Intent, String)
591 * Context.sendOrderedBroadcast}. All current result data is replaced
592 * by the value given to this method.
593 *
594 * <p><strong>This method does not work with non-ordered broadcasts such
595 * as those sent with {@link Context#sendBroadcast(Intent)
596 * Context.sendBroadcast}</strong></p>
597 *
598 * @param code The new result code. Often uses the
599 * Activity {@link android.app.Activity#RESULT_CANCELED} and
600 * {@link android.app.Activity#RESULT_OK} constants, though the
601 * actual meaning of this value is ultimately up to the broadcaster.
602 * @param data The new result data. This is an arbitrary
603 * string whose interpretation is up to the broadcaster; may be null.
604 * @param extras The new extra data map. This is a Bundle
605 * holding arbitrary data, whose interpretation is up to the
606 * broadcaster. Can be set to null. This completely
607 * replaces the current map (if any).
608 */
609 public final void setResult(int code, String data, Bundle extras) {
610 checkSynchronousHint();
Dianne Hackborne829fef2010-10-26 17:44:01 -0700611 mPendingResult.mResultCode = code;
612 mPendingResult.mResultData = data;
613 mPendingResult.mResultExtras = extras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 }
615
616 /**
617 * Returns the flag indicating whether or not this receiver should
618 * abort the current broadcast.
619 *
620 * @return True if the broadcast should be aborted.
621 */
622 public final boolean getAbortBroadcast() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700623 return mPendingResult != null ? mPendingResult.mAbortBroadcast : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 }
625
626 /**
627 * Sets the flag indicating that this receiver should abort the
628 * current broadcast; only works with broadcasts sent through
629 * {@link Context#sendOrderedBroadcast(Intent, String)
630 * Context.sendOrderedBroadcast}. This will prevent
631 * any other broadcast receivers from receiving the broadcast. It will still
632 * call {@link #onReceive} of the BroadcastReceiver that the caller of
633 * {@link Context#sendOrderedBroadcast(Intent, String)
634 * Context.sendOrderedBroadcast} passed in.
635 *
636 * <p><strong>This method does not work with non-ordered broadcasts such
637 * as those sent with {@link Context#sendBroadcast(Intent)
638 * Context.sendBroadcast}</strong></p>
639 */
640 public final void abortBroadcast() {
641 checkSynchronousHint();
Dianne Hackborne829fef2010-10-26 17:44:01 -0700642 mPendingResult.mAbortBroadcast = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 }
644
645 /**
646 * Clears the flag indicating that this receiver should abort the current
647 * broadcast.
648 */
649 public final void clearAbortBroadcast() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700650 if (mPendingResult != null) {
651 mPendingResult.mAbortBroadcast = false;
652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 }
654
655 /**
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700656 * Returns true if the receiver is currently processing an ordered
657 * broadcast.
658 */
659 public final boolean isOrderedBroadcast() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700660 return mPendingResult != null ? mPendingResult.mOrderedHint : false;
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700661 }
662
663 /**
664 * Returns true if the receiver is currently processing the initial
665 * value of a sticky broadcast -- that is, the value that was last
666 * broadcast and is currently held in the sticky cache, so this is
667 * not directly the result of a broadcast right now.
668 */
669 public final boolean isInitialStickyBroadcast() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700670 return mPendingResult != null ? mPendingResult.mInitialStickyHint : false;
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700671 }
672
673 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 * For internal use, sets the hint about whether this BroadcastReceiver is
675 * running in ordered mode.
676 */
677 public final void setOrderedHint(boolean isOrdered) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700678 // Accidentally left in the SDK.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 }
680
681 /**
Dianne Hackborne829fef2010-10-26 17:44:01 -0700682 * For internal use to set the result data that is active. @hide
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700683 */
Dianne Hackborne829fef2010-10-26 17:44:01 -0700684 public final void setPendingResult(PendingResult result) {
685 mPendingResult = result;
686 }
687
688 /**
689 * For internal use to set the result data that is active. @hide
690 */
691 public final PendingResult getPendingResult() {
692 return mPendingResult;
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700693 }
694
695 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 * Control inclusion of debugging help for mismatched
697 * calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter)
698 * Context.registerReceiver()}.
699 * If called with true, before given to registerReceiver(), then the
700 * callstack of the following {@link Context#unregisterReceiver(BroadcastReceiver)
701 * Context.unregisterReceiver()} call is retained, to be printed if a later
702 * incorrect unregister call is made. Note that doing this requires retaining
703 * information about the BroadcastReceiver for the lifetime of the app,
704 * resulting in a leak -- this should only be used for debugging.
705 */
706 public final void setDebugUnregister(boolean debug) {
707 mDebugUnregister = debug;
708 }
709
710 /**
711 * Return the last value given to {@link #setDebugUnregister}.
712 */
713 public final boolean getDebugUnregister() {
714 return mDebugUnregister;
715 }
716
717 void checkSynchronousHint() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700718 if (mPendingResult == null) {
719 throw new IllegalStateException("Call while result is not pending");
720 }
721
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700722 // Note that we don't assert when receiving the initial sticky value,
723 // since that may have come from an ordered broadcast. We'll catch
724 // them later when the real broadcast happens again.
Dianne Hackborne829fef2010-10-26 17:44:01 -0700725 if (mPendingResult.mOrderedHint || mPendingResult.mInitialStickyHint) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 return;
727 }
728 RuntimeException e = new RuntimeException(
729 "BroadcastReceiver trying to return result during a non-ordered broadcast");
730 e.fillInStackTrace();
731 Log.e("BroadcastReceiver", e.getMessage(), e);
732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733}
734