BroadcastReceiver.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
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
17package android.content;
18
19import android.os.Bundle;
20import android.util.Log;
21
22/**
23 * Base class for code that will receive intents sent by sendBroadcast().
24 * You can either dynamically register an instance of this class with
25 * {@link Context#registerReceiver Context.registerReceiver()}
26 * or statically publish an implementation through the
27 * {@link android.R.styleable#AndroidManifestReceiver <receiver>}
28 * tag in your <code>AndroidManifest.xml</code>. <em><strong>Note:</strong></em>
29 * &nbsp;&nbsp;&nbsp;If registering a receiver in your
30 * {@link android.app.Activity#onResume() Activity.onResume()}
31 * implementation, you should unregister it in
32 * {@link android.app.Activity#onPause() Activity.onPause()}.
33 * (You won't receive intents when paused,
34 * and this will cut down on unnecessary system overhead). Do not unregister in
35 * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()},
36 * because this won't be called if the user moves back in the history
37 * stack.
38 *
39 * <p>There are two major classes of broadcasts that can be received:</p>
40 * <ul>
41 * <li> <b>Normal broadcasts</b> (sent with {@link Context#sendBroadcast(Intent)
42 * Context.sendBroadcast}) are completely asynchronous.  All receivers of the
43 * broadcast are run, in an undefined order, often at the same time.  This is
44 * more efficient, but means that receivers can not use the result or abort
45 * APIs included here.
46 * <li> <b>Ordered broadcasts</b> (sent with {@link Context#sendOrderedBroadcast(Intent, String)
47 * Context.sendOrderedBroadcast}) are delivered to one receiver at a time.
48 * As each receiver executes in turn, it can propagate a result to the next
49 * receiver, or it can completely abort the broadcast so that it won't be passed
50 * to other receivers.  The order receivers runs in can be controlled with the
51 * {@link android.R.styleable#AndroidManifestIntentFilter_priority
52 * android:priority} attribute of the matching intent-filter; receivers with
53 * the same priority will be run in an arbitrary order.
54 * </ul>
55 *
56 * <p>Even in the case of normal broadcasts, the system may in some
57 * situations revert to delivering the broadcast one receiver at a time.  In
58 * particular, for receivers that may require the creation of a process, only
59 * one will be run at a time to avoid overloading the system with new processes.
60 * In this situation, however, the non-ordered semantics hold: these receivers
61 * can not return results or abort their broadcast.</p>
62 *
63 * <p>Note that, although the Intent class is used for sending and receiving
64 * these broadcasts, the Intent broadcast mechanism here is completely separate
65 * from Intents that are used to start Activities with
66 * {@link Context#startActivity Context.startActivity()}.
67 * There is no way for an BroadcastReceiver
68 * to see or capture Intents used with startActivity(); likewise, when
69 * you broadcast an Intent, you will never find or start an Activity.
70 * These two operations are semantically very different: starting an
71 * Activity with an Intent is a foreground operation that modifies what the
72 * user is currently interacting with; broadcasting an Intent is a background
73 * operation that the user is not normally aware of.
74 *
75 * <p>The BroadcastReceiver class (when launched as a component through
76 * a manifest's {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
77 * tag) is an important part of an
78 * <a href="{@docRoot}intro/lifecycle.html">application's overall lifecycle</a>.</p>
79 *
80 * <p>Topics covered here:
81 * <ol>
82 * <li><a href="#ReceiverLifecycle">Receiver Lifecycle</a>
83 * <li><a href="#Permissions">Permissions</a>
84 * <li><a href="#ProcessLifecycle">Process Lifecycle</a>
85 * </ol>
86 *
87 * <a name="ReceiverLifecycle"></a>
88 * <h3>Receiver Lifecycle</h3>
89 *
90 * <p>A BroadcastReceiver object is only valid for the duration of the call
91 * to {@link #onReceive}.  Once your code returns from this function,
92 * the system considers the object to be finished and no longer active.
93 *
94 * <p>This has important repercussions to what you can do in an
95 * {@link #onReceive} implementation: anything that requires asynchronous
96 * operation is not available, because you will need to return from the
97 * function to handle the asynchronous operation, but at that point the
98 * BroadcastReceiver is no longer active and thus the system is free to kill
99 * its process before the asynchronous operation completes.
100 *
101 * <p>In particular, you may <i>not</i> show a dialog or bind to a service from
102 * within an BroadcastReceiver.  For the former, you should instead use the
103 * {@link android.app.NotificationManager} API.  For the latter, you can
104 * use {@link android.content.Context#startService Context.startService()} to
105 * send a command to the service.
106 *
107 * <a name="Permissions"></a>
108 * <h3>Permissions</h3>
109 *
110 * <p>Access permissions can be enforced by either the sender or receiver
111 * of an Intent.
112 *
113 * <p>To enforce a permission when sending, you supply a non-null
114 * <var>permission</var> argument to
115 * {@link Context#sendBroadcast(Intent, String)} or
116 * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}.
117 * Only receivers who have been granted this permission
118 * (by requesting it with the
119 * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
120 * tag in their <code>AndroidManifest.xml</code>) will be able to receive
121 * the broadcast.
122 *
123 * <p>To enforce a permission when receiving, you supply a non-null
124 * <var>permission</var> when registering your receiver -- either when calling
125 * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)}
126 * or in the static
127 * {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
128 * tag in your <code>AndroidManifest.xml</code>.  Only broadcasters who have
129 * been granted this permission (by requesting it with the
130 * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
131 * tag in their <code>AndroidManifest.xml</code>) will be able to send an
132 * Intent to the receiver.
133 *
134 * <p>See the <a href="{@docRoot}devel/security.html">Security Model</a>
135 * document for more information on permissions and security in general.
136 *
137 * <a name="ProcessLifecycle"></a>
138 * <h3>Process Lifecycle</h3>
139 *
140 * <p>A process that is currently executing an BroadcastReceiver (that is,
141 * currently running the code in its {@link #onReceive} method) is
142 * considered to be a foreground process and will be kept running by the
143 * system except under cases of extreme memory pressure.
144 *
145 * <p>Once you return from onReceive(), the BroadcastReceiver is no longer
146 * active, and its hosting process is only as important as any other application
147 * components that are running in it.  This is especially important because if
148 * that process was only hosting the BroadcastReceiver (a common case for
149 * applications that the user has never or not recently interacted with), then
150 * upon returning from onReceive() the system will consider its process
151 * to be empty and aggressively kill it so that resources are available for other
152 * more important processes.
153 *
154 * <p>This means that for longer-running operations you will often use
155 * a {@link android.app.Service} in conjunction with an BroadcastReceiver to keep
156 * the containing process active for the entire time of your operation.
157 */
158public abstract class BroadcastReceiver {
159    public BroadcastReceiver() {
160    }
161
162    /**
163     * This method is called when the BroadcastReceiver is receiving an Intent
164     * broadcast.  During this time you can use the other methods on
165     * BroadcastReceiver to view/modify the current result values.  The function
166     * is normally called from the main thread of its process, so you should
167     * never perform long-running operations in it (there is a timeout of
168     * 10 seconds that the system allows before considering the receiver to
169     * be blocked and a candidate to be killed). You cannot launch a popup dialog
170     * in your implementation of onReceive().
171     *
172     * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
173     * then the object is no longer alive after returning from this
174     * function.</b>  This means you should not perform any operations that
175     * return a result to you asynchronously -- in particular, for interacting
176     * with services, you should use
177     * {@link Context#startService(Intent)} instead of
178     * {@link Context#bindService(Intent, ServiceConnection, int)}.
179     *
180     * @param context The Context in which the receiver is running.
181     * @param intent The Intent being received.
182     */
183    public abstract void onReceive(Context context, Intent intent);
184
185    /**
186     * Change the current result code of this broadcast; only works with
187     * broadcasts sent through
188     * {@link Context#sendOrderedBroadcast(Intent, String)
189     * Context.sendOrderedBroadcast}.  Often uses the
190     * Activity {@link android.app.Activity#RESULT_CANCELED} and
191     * {@link android.app.Activity#RESULT_OK} constants, though the
192     * actual meaning of this value is ultimately up to the broadcaster.
193     *
194     * <p><strong>This method does not work with non-ordered broadcasts such
195     * as those sent with {@link Context#sendBroadcast(Intent)
196     * Context.sendBroadcast}</strong></p>
197     *
198     * @param code The new result code.
199     *
200     * @see #setResult(int, String, Bundle)
201     */
202    public final void setResultCode(int code) {
203        checkSynchronousHint();
204        mResultCode = code;
205    }
206
207    /**
208     * Retrieve the current result code, as set by the previous receiver.
209     *
210     * @return int The current result code.
211     */
212    public final int getResultCode() {
213        return mResultCode;
214    }
215
216    /**
217     * Change the current result data of this broadcast; only works with
218     * broadcasts sent through
219     * {@link Context#sendOrderedBroadcast(Intent, String)
220     * Context.sendOrderedBroadcast}.  This is an arbitrary
221     * string whose interpretation is up to the broadcaster.
222     *
223     * <p><strong>This method does not work with non-ordered broadcasts such
224     * as those sent with {@link Context#sendBroadcast(Intent)
225     * Context.sendBroadcast}</strong></p>
226     *
227     * @param data The new result data; may be null.
228     *
229     * @see #setResult(int, String, Bundle)
230     */
231    public final void setResultData(String data) {
232        checkSynchronousHint();
233        mResultData = data;
234    }
235
236    /**
237     * Retrieve the current result data, as set by the previous receiver.
238     * Often this is null.
239     *
240     * @return String The current result data; may be null.
241     */
242    public final String getResultData() {
243        return mResultData;
244    }
245
246    /**
247     * Change the current result extras of this broadcast; only works with
248     * broadcasts sent through
249     * {@link Context#sendOrderedBroadcast(Intent, String)
250     * Context.sendOrderedBroadcast}.  This is a Bundle
251     * holding arbitrary data, whose interpretation is up to the
252     * broadcaster.  Can be set to null.  Calling this method completely
253     * replaces the current map (if any).
254     *
255     * <p><strong>This method does not work with non-ordered broadcasts such
256     * as those sent with {@link Context#sendBroadcast(Intent)
257     * Context.sendBroadcast}</strong></p>
258     *
259     * @param extras The new extra data map; may be null.
260     *
261     * @see #setResult(int, String, Bundle)
262     */
263    public final void setResultExtras(Bundle extras) {
264        checkSynchronousHint();
265        mResultExtras = extras;
266    }
267
268    /**
269     * Retrieve the current result extra data, as set by the previous receiver.
270     * Any changes you make to the returned Map will be propagated to the next
271     * receiver.
272     *
273     * @param makeMap If true then a new empty Map will be made for you if the
274     *                current Map is null; if false you should be prepared to
275     *                receive a null Map.
276     *
277     * @return Map The current extras map.
278     */
279    public final Bundle getResultExtras(boolean makeMap) {
280        Bundle e = mResultExtras;
281        if (!makeMap) return e;
282        if (e == null) mResultExtras = e = new Bundle();
283        return e;
284    }
285
286    /**
287     * Change all of the result data returned from this broadcasts; only works
288     * with broadcasts sent through
289     * {@link Context#sendOrderedBroadcast(Intent, String)
290     * Context.sendOrderedBroadcast}.  All current result data is replaced
291     * by the value given to this method.
292     *
293     * <p><strong>This method does not work with non-ordered broadcasts such
294     * as those sent with {@link Context#sendBroadcast(Intent)
295     * Context.sendBroadcast}</strong></p>
296     *
297     * @param code The new result code.  Often uses the
298     * Activity {@link android.app.Activity#RESULT_CANCELED} and
299     * {@link android.app.Activity#RESULT_OK} constants, though the
300     * actual meaning of this value is ultimately up to the broadcaster.
301     * @param data The new result data.  This is an arbitrary
302     * string whose interpretation is up to the broadcaster; may be null.
303     * @param extras The new extra data map.  This is a Bundle
304     * holding arbitrary data, whose interpretation is up to the
305     * broadcaster.  Can be set to null.  This completely
306     * replaces the current map (if any).
307     */
308    public final void setResult(int code, String data, Bundle extras) {
309        checkSynchronousHint();
310        mResultCode = code;
311        mResultData = data;
312        mResultExtras = extras;
313    }
314
315    /**
316     * Returns the flag indicating whether or not this receiver should
317     * abort the current broadcast.
318     *
319     * @return True if the broadcast should be aborted.
320     */
321    public final boolean getAbortBroadcast() {
322        return mAbortBroadcast;
323    }
324
325    /**
326     * Sets the flag indicating that this receiver should abort the
327     * current broadcast; only works with broadcasts sent through
328     * {@link Context#sendOrderedBroadcast(Intent, String)
329     * Context.sendOrderedBroadcast}.  This will prevent
330     * any other broadcast receivers from receiving the broadcast. It will still
331     * call {@link #onReceive} of the BroadcastReceiver that the caller of
332     * {@link Context#sendOrderedBroadcast(Intent, String)
333     * Context.sendOrderedBroadcast} passed in.
334     *
335     * <p><strong>This method does not work with non-ordered broadcasts such
336     * as those sent with {@link Context#sendBroadcast(Intent)
337     * Context.sendBroadcast}</strong></p>
338     */
339    public final void abortBroadcast() {
340        checkSynchronousHint();
341        mAbortBroadcast = true;
342    }
343
344    /**
345     * Clears the flag indicating that this receiver should abort the current
346     * broadcast.
347     */
348    public final void clearAbortBroadcast() {
349        mAbortBroadcast = false;
350    }
351
352    /**
353     * For internal use, sets the hint about whether this BroadcastReceiver is
354     * running in ordered mode.
355     */
356    public final void setOrderedHint(boolean isOrdered) {
357        mOrderedHint = isOrdered;
358    }
359
360    /**
361     * Control inclusion of debugging help for mismatched
362     * calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter)
363     * Context.registerReceiver()}.
364     * If called with true, before given to registerReceiver(), then the
365     * callstack of the following {@link Context#unregisterReceiver(BroadcastReceiver)
366     * Context.unregisterReceiver()} call is retained, to be printed if a later
367     * incorrect unregister call is made.  Note that doing this requires retaining
368     * information about the BroadcastReceiver for the lifetime of the app,
369     * resulting in a leak -- this should only be used for debugging.
370     */
371    public final void setDebugUnregister(boolean debug) {
372        mDebugUnregister = debug;
373    }
374
375    /**
376     * Return the last value given to {@link #setDebugUnregister}.
377     */
378    public final boolean getDebugUnregister() {
379        return mDebugUnregister;
380    }
381
382    void checkSynchronousHint() {
383        if (mOrderedHint) {
384            return;
385        }
386        RuntimeException e = new RuntimeException(
387                "BroadcastReceiver trying to return result during a non-ordered broadcast");
388        e.fillInStackTrace();
389        Log.e("BroadcastReceiver", e.getMessage(), e);
390    }
391
392    private int mResultCode;
393    private String mResultData;
394    private Bundle mResultExtras;
395    private boolean mAbortBroadcast;
396    private boolean mDebugUnregister;
397    private boolean mOrderedHint;
398}
399
400