Home | History | Annotate | Download | only in run-background-service
      1 page.title=Reporting Work Status
      2 trainingnavtop=true
      3 @jd:body
      4 <div id="tb-wrapper">
      5 <div id="tb">
      6 <h2>This lesson teaches you to</h2>
      7 <ol>
      8     <li>
      9         <a href="#ReportStatus">Report Status From an IntentService</a>
     10     </li>
     11     <li>
     12         <a href="#ReceiveStatus">Receive Status Broadcasts from an IntentService</a>
     13     </li>
     14 </ol>
     15 <h2>You should also read</h2>
     16 <ul>
     17     <li>
     18         <a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
     19     </li>
     20     <li>
     21         The section <b>Broadcast receivers</b> in the
     22     <a href="{@docRoot}guide/components/fundamentals.html#Components">Application Components</a>
     23         API guide.
     24     </li>
     25 </ul>
     26 <h2>Try it out</h2>
     27 
     28 <div class="download-box">
     29     <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a>
     30     <p class="filename">ThreadSample.zip</p>
     31 </div>
     32 
     33 </div>
     34 </div>
     35 <p>
     36     This lesson shows you how to report the status of a work request run in a background service
     37     to the component that sent the request. This allows you, for example, to report the status of
     38     the request in an {@link android.app.Activity} object's UI. The recommended way to send and
     39     receive status is to use a {@link android.support.v4.content.LocalBroadcastManager}, which
     40     limits broadcast {@link android.content.Intent} objects to components in your own app.
     41 </p>
     42 <h2 id="ReportStatus">Report Status From an IntentService</h2>
     43 
     44 <p>
     45     To send the status of a work request in an {@link android.app.IntentService} to other
     46     components, first create an {@link android.content.Intent} that contains the status in its
     47     extended data. As an option, you can add an action and data URI to this
     48     {@link android.content.Intent}.
     49 </p>
     50 <p>
     51     Next, send the {@link android.content.Intent} by calling
     52     {@link android.support.v4.content.LocalBroadcastManager#sendBroadcast
     53     LocalBroadcastManager.sendBroadcast()}. This sends the {@link android.content.Intent} to any
     54     component in your application that has registered to receive it.
     55     To get an instance of {@link android.support.v4.content.LocalBroadcastManager}, call
     56     {@link android.support.v4.content.LocalBroadcastManager#getInstance getInstance()}.
     57 </p>
     58 <p>
     59     For example:
     60 </p>
     61 <pre>
     62 public final class Constants {
     63     ...
     64     // Defines a custom Intent action
     65     public static final String BROADCAST_ACTION =
     66         "com.example.android.threadsample.BROADCAST";
     67     ...
     68     // Defines the key for the status "extra" in an Intent
     69     public static final String EXTENDED_DATA_STATUS =
     70         "com.example.android.threadsample.STATUS";
     71     ...
     72 }
     73 public class RSSPullService extends IntentService {
     74 ...
     75     /*
     76      * Creates a new Intent containing a Uri object
     77      * BROADCAST_ACTION is a custom Intent action
     78      */
     79     Intent localIntent =
     80             new Intent(Constants.BROADCAST_ACTION)
     81             // Puts the status into the Intent
     82             .putExtra(Constants.EXTENDED_DATA_STATUS, status);
     83     // Broadcasts the Intent to receivers in this app.
     84     LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
     85 ...
     86 }
     87 </pre>
     88 <p>
     89     The next step is to handle the incoming broadcast {@link android.content.Intent} objects in
     90     the component that sent the original work request.
     91 </p>
     92 <h2 id="ReceiveStatus">Receive Status Broadcasts from an IntentService</h2>
     93 <p>
     94     
     95     To receive broadcast {@link android.content.Intent} objects, use a subclass of
     96     {@link android.content.BroadcastReceiver}. In the subclass, implement the
     97     {@link android.content.BroadcastReceiver#onReceive BroadcastReceiver.onReceive()} callback
     98     method, which {@link android.support.v4.content.LocalBroadcastManager} invokes when it receives
     99     an {@link android.content.Intent}. {@link android.support.v4.content.LocalBroadcastManager}
    100     passes the incoming {@link android.content.Intent} to
    101     {@link android.content.BroadcastReceiver#onReceive BroadcastReceiver.onReceive()}.
    102 </p>
    103 <p>
    104     For example:
    105 </p>
    106 <pre>
    107 // Broadcast receiver for receiving status updates from the IntentService
    108 private class ResponseReceiver extends BroadcastReceiver
    109 {
    110     // Prevents instantiation
    111     private DownloadStateReceiver() {
    112     }
    113     // Called when the BroadcastReceiver gets an Intent it's registered to receive
    114     &#64;
    115     public void onReceive(Context context, Intent intent) {
    116 ...
    117         /*
    118          * Handle Intents here.
    119          */
    120 ...
    121     }
    122 }
    123 </pre>
    124 <p>
    125     Once you've defined the {@link android.content.BroadcastReceiver}, you can define filters
    126     for it that match specific actions, categories, and data. To do this, create
    127     an {@link android.content.IntentFilter}. This first snippet shows how to define the filter:
    128 </p>
    129 <pre>
    130 // Class that displays photos
    131 public class DisplayActivity extends FragmentActivity {
    132     ...
    133     public void onCreate(Bundle stateBundle) {
    134         ...
    135         super.onCreate(stateBundle);
    136         ...
    137         // The filter's action is BROADCAST_ACTION
    138         IntentFilter mStatusIntentFilter = new IntentFilter(
    139                 Constants.BROADCAST_ACTION);
    140     
    141         // Adds a data filter for the HTTP scheme
    142         mStatusIntentFilter.addDataScheme("http");
    143         ...
    144 </pre>
    145 <p>
    146     To register the {@link android.content.BroadcastReceiver} and the
    147     {@link android.content.IntentFilter} with the system, get an instance of
    148     {@link android.support.v4.content.LocalBroadcastManager} and call its
    149     {@link android.support.v4.content.LocalBroadcastManager#registerReceiver registerReceiver()}
    150     method. This next snippet shows how to register the {@link android.content.BroadcastReceiver}
    151     and its {@link android.content.IntentFilter}:
    152 </p>
    153 <pre>
    154         // Instantiates a new DownloadStateReceiver
    155         DownloadStateReceiver mDownloadStateReceiver =
    156                 new DownloadStateReceiver();
    157         // Registers the DownloadStateReceiver and its intent filters
    158         LocalBroadcastManager.getInstance(this).registerReceiver(
    159                 mDownloadStateReceiver,
    160                 mStatusIntentFilter);
    161         ...
    162 </pre>
    163 <p>
    164     A single {@link android.content.BroadcastReceiver} can handle more than one type of broadcast
    165     {@link android.content.Intent} object, each with its own action. This feature allows you to
    166     run different code for each action, without having to define a separate
    167     {@link android.content.BroadcastReceiver} for each action. To define another
    168     {@link android.content.IntentFilter} for the same
    169     {@link android.content.BroadcastReceiver}, create the {@link android.content.IntentFilter} and
    170     repeat the call to
    171     {@link android.support.v4.content.LocalBroadcastManager#registerReceiver registerReceiver()}.
    172     For example:
    173 </p>
    174 <pre>
    175         /*
    176          * Instantiates a new action filter.
    177          * No data filter is needed.
    178          */
    179         statusIntentFilter = new IntentFilter(Constants.ACTION_ZOOM_IMAGE);
    180         ...
    181         // Registers the receiver with the new filter
    182         LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
    183                 mDownloadStateReceiver,
    184                 mIntentFilter);
    185 </pre>
    186 <p>
    187     Sending an broadcast {@link android.content.Intent} doesn't start or resume an
    188     {@link android.app.Activity}. The {@link android.content.BroadcastReceiver} for an
    189     {@link android.app.Activity} receives and processes {@link android.content.Intent} objects even
    190     when your app is in the background, but doesn't force your app to the foreground. If you
    191     want to notify the user about an event that happened in the background while your app was not
    192     visible, use a {@link android.app.Notification}. <i>Never</i> start an
    193     {@link android.app.Activity} in response to an incoming broadcast
    194     {@link android.content.Intent}.
    195 </p>
    196 <p>
    197     
    198 </p>
    199 
    200