1page.title=Background Optimizations
2page.metaDescription=New restrictions to implicit broadcasts.
3page.keywords="android N", "implicit broadcasts", "job scheduler"
4page.image=images/cards/card-nyc_2x.jpg
5
6@jd:body
7
8<div id="qv-wrapper">
9  <div id="qv">
10    <h2>
11      In this document
12    </h2>
13
14    <ol>
15      <li>
16        <a href="#connectivity-action">Restrictions on CONNECTIVITY_ACTION</a>
17      </li>
18
19      <li>
20        <a href="#sched-jobs">Scheduling Network Jobs on Unmetered
21        Connections</a>
22      </li>
23
24      <li>
25        <a href="#monitor-conn">Monitoring Network Connectivity While the App
26        is Running</a>
27      </li>
28
29      <li>
30        <a href="#media-broadcasts">Restrictions on NEW_PICTURE and
31        NEW_VIDEO</a>
32      </li>
33
34      <li>
35        <a href="#new-jobinfo">New JobInfo methods</a>
36      </li>
37
38      <li>
39        <a href="#new-jobparam">New JobParameter Methods</a>
40      </li>
41
42      <li>
43        <a href="#further-optimization">Further Optimizing Your App</a>
44      </li>
45    </ol>
46  </div>
47</div>
48
49<p>
50  Background processes can be memory- and battery-intensive. For example, an
51  implicit broadcast may start many background processes that have registered
52  to listen for it, even if those processes may not do much work. This can have
53  a substantial impact on both device performance and user experience.
54</p>
55
56<p>
57  To alleviate this issue, Android N applies the following
58  restrictions:
59</p>
60
61<ul>
62  <li>Apps targeting the Preview do not receive {@link
63  android.net.ConnectivityManager#CONNECTIVITY_ACTION} broadcasts if they
64  register to receive them in their manifest. Apps that are running can still
65  listen for {@code CONNECTIVITY_CHANGE} on their main thread by registering a
66  {@link android.content.BroadcastReceiver} with {@link
67  android.content.Context#registerReceiver Context.registerReceiver()}.
68  </li>
69
70  <li>Apps cannot send or receive {@link
71  android.hardware.Camera#ACTION_NEW_PICTURE} or {@link
72  android.hardware.Camera#ACTION_NEW_VIDEO} broadcasts. This optimization
73  affects all apps, not only those targeting the Preview.
74  </li>
75</ul>
76
77<p>
78  If your app uses any of these intents, you should remove dependencies on
79  them as soon as possible so that you can target Android N devices properly.
80  The Android framework provides several solutions to mitigate the need for
81  these implicit broadcasts. For example, {@link android.app.job.JobScheduler}
82  and <a href=
83  "https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
84  {@code GcmNetworkManager}</a> provide robust mechanisms to schedule network
85  operations when specified conditions, such as a connection to an unmetered
86  network, are met. You can now also use {@link android.app.job.JobScheduler}
87  to react to changes to content providers. {@link android.app.job.JobInfo}
88  objects encapsulate the parameters that {@link android.app.job.JobScheduler}
89  uses to schedule your job. When the conditions of the job are met, the system
90  executes this job on your app's {@link android.app.job.JobService}.
91</p>
92
93<p>
94  In this document, we will learn how to use alternative methods, such as
95  {@link android.app.job.JobScheduler}, to adapt your app to these new
96  restrictions.
97</p>
98
99<h2 id="connectivity-action">
100  Restrictions on CONNECTIVITY_ACTION
101</h2>
102
103<p>
104  Apps targeting the Android N do not receive {@link
105  android.net.ConnectivityManager#CONNECTIVITY_ACTION} broadcasts if they
106  register to receive them in their manifest, and processes that depend on this
107  broadcast will not start. This could pose a problem for apps that want
108  to listen for network changes or perform bulk network activities when the
109  device connects to an unmetered network. Several solutions to get around this
110  restriction already exist in the Android framework, but choosing the right
111  one depends on what you want your app to accomplish.
112</p>
113
114<p class="note">
115  <strong>Note:</strong> A {@link android.content.BroadcastReceiver} registered with
116  {@link android.content.Context#registerReceiver Context.registerReceiver()}
117  continues to receive these broadcasts while the app is running.
118</p>
119
120<h3 id="sched-jobs">
121  Scheduling Network Jobs on Unmetered Connections
122</h3>
123
124<p>
125  When using the {@link android.app.job.JobInfo.Builder JobInfo.Builder} class
126  to build your {@link android.app.job.JobInfo} object, apply the {@link
127  android.app.job.JobInfo.Builder#setRequiredNetworkType
128  setRequiredNetworkType()} method and pass {@link android.app.job.JobInfo
129  JobInfo.NETWORK_TYPE_UNMETERED} as a job parameter. The following code sample
130  schedules a service to run when the device connects to an unmetered
131  network and is charging:
132</p>
133
134<pre>
135public static final int MY_BACKGROUND_JOB = 0;
136...
137public static void scheduleJob(Context context) {
138  JobScheduler js =
139      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
140  JobInfo job = new JobInfo.Builder(
141    MY_BACKGROUND_JOB,
142    new ComponentName(context, MyJobService.class))
143      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
144      .setRequiresCharging(true)
145      .build();
146  js.schedule(job);
147}
148</pre>
149
150<p>
151  When the conditions for your job are met, your app receives a callback to run
152  the {@link android.app.job.JobService#onStartJob onStartJob()} method in the
153  specified {@code JobService.class}. To see more examples of {@link
154  android.app.job.JobScheduler} implementation, see the <a href=
155  "{@docRoot}samples/JobScheduler/index.html">JobScheduler sample app</a>.
156</p>
157
158<p>
159  Applications that use GMSCore services, and target Android 5.0 (API level 21)
160  or lower, can use <a href=
161  "https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
162  {@code GcmNetworkManager}</a> and specify {@code Task.NETWORK_STATE_UNMETERED}.
163</p>
164
165<h3 id="monitor-conn">
166  Monitoring Network Connectivity While the App is Running
167</h3>
168
169<p>
170  Apps that are running can still listen for {@code CONNECTIVITY_CHANGE} with a
171  registered {@link android.content.BroadcastReceiver}. However, the {@link
172  android.net.ConnectivityManager} API provides a more robust method to request
173  a callback only when specified network conditions are met.
174</p>
175
176<p>
177  {@link android.net.NetworkRequest} objects define the parameters of the
178  network callback in terms of {@link android.net.NetworkCapabilities}. You
179  create {@link android.net.NetworkRequest} objects with the {@link
180  android.net.NetworkRequest.Builder NetworkRequest.Builder} class. {@link
181  android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest,
182  android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()}
183  then passes the {@link android.net.NetworkRequest} object to the system. When
184  the network conditions are met, the app receives a callback to execute the
185  {@link android.net.ConnectivityManager.NetworkCallback#onAvailable
186  onAvailable()} method defined in its {@link
187  android.net.ConnectivityManager.NetworkCallback} class.
188</p>
189
190<p>
191  The app continues to receive callbacks until either the app exits or it calls
192  {@link android.net.ConnectivityManager#unregisterNetworkCallback
193  unregisterNetworkCallback()}.
194</p>
195
196<h2 id="media-broadcasts">
197  Restrictions on NEW_PICTURE and NEW_VIDEO
198</h2>
199
200<p>
201  In the Android N, apps are not able to send or receive {@link
202  android.hardware.Camera#ACTION_NEW_PICTURE} or {@link
203  android.hardware.Camera#ACTION_NEW_VIDEO} broadcasts. This restriction helps
204  alleviate the performance and user experience impacts when several apps must
205  wake up in order to process a new image or video. Android N
206  extends {@link android.app.job.JobInfo} and {@link
207  android.app.job.JobParameters} to provide an alternative solution.
208</p>
209
210<h3 id="new-jobinfo">
211  New JobInfo methods
212</h3>
213
214<p>
215  To trigger jobs on content URI changes, Android N extends
216  the {@link android.app.job.JobInfo} API with the following methods:
217</p>
218
219<dl>
220  <dt>
221    {@code JobInfo.TriggerContentUri()}
222  </dt>
223
224  <dd>
225    Encapsulates parameters required to trigger a job on content URI changes.
226  </dd>
227
228  <dt>
229    {@code JobInfo.Builder.addTriggerContentUri()}
230  </dt>
231
232  <dd>
233    Passes a {@code TriggerContentUri} object to {@link
234    android.app.job.JobInfo}. A {@link android.database.ContentObserver}
235    monitors the encapsulated content URI. If there are multiple {@code
236    TriggerContentUri} objects associated with a job, the system provides a
237    callback even if it reports a change in only one of the content URIs.
238  </dd>
239
240  <dd>
241    Add the {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} flag to
242    trigger the job if any descendants of the given URI change. This flag
243    corresponds to the {@code notifyForDescendants} parameter passed to {@link
244    android.content.ContentResolver#registerContentObserver
245    registerContentObserver()}.
246  </dd>
247</dl>
248
249<p class="note">
250  <strong>Note:</strong> {@code TriggerContentUri()} cannot be used in
251  combination with {@link android.app.job.JobInfo.Builder#setPeriodic
252  setPeriodic()} or {@link android.app.job.JobInfo.Builder#setPersisted
253  setPersisted()}. To continually monitor for content changes, schedule a new
254  {@link android.app.job.JobInfo} before the app’s {@link
255  android.app.job.JobService} finishes handling the most recent callback.
256</p>
257
258<p>
259  The following sample code schedules a job to trigger when the system reports
260  a change to the content URI, {@code MEDIA_URI}:
261</p>
262
263<pre>
264public static final int MY_BACKGROUND_JOB = 0;
265...
266public static void scheduleJob(Context context) {
267  JobScheduler js =
268          (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
269  JobInfo.Builder builder = new JobInfo.Builder(
270          MY_BACKGROUND_JOB,
271          new ComponentName(context, MediaContentJob.class));
272  builder.addTriggerContentUri(
273          new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
274          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
275  js.schedule(builder.build());
276}
277</pre>
278<p>
279  When the system reports a change in the specified content URI(s), your app
280  receives a callback and a {@link android.app.job.JobParameters} object is
281  passed to the {@link android.app.job.JobService#onStartJob onStartJob()}
282  method in {@code MediaContentJob.class}.
283</p>
284
285<h3 id="new-jobparam">
286  New JobParameter Methods
287</h3>
288
289<p>
290  Android N also extends {@link android.app.job.JobParameters} to
291  allow your app to receive useful information about what content authorities
292  and URIs triggered the job:
293</p>
294
295<dl>
296  <dt>
297    {@code Uri[] getTriggeredContentUris()}
298  </dt>
299
300  <dd>
301    Returns an array of URIs that have triggered the job. This will be {@code
302    null} if either no URIs have triggered the job (for example, the job was
303    triggered due to a deadline or some other reason), or the number of changed
304    URIs is greater than 50.
305  </dd>
306
307  <dt>
308    {@code String[] getTriggeredContentAuthorities()}
309  </dt>
310
311  <dd>
312    Returns a string array of content authorities that have triggered the job.
313    If the returned array is not {@code null}, use {@code getTriggeredContentUris()}
314    to retrieve the details of which URIs have changed.
315  </dd>
316</dl>
317
318<p>
319  The following sample code overrides the {@link
320  android.app.job.JobService#onStartJob JobService.onStartJob()} method and
321  records the content authorities and URIs that have triggered the job:
322</p>
323
324<pre>
325&#64;Override
326public boolean onStartJob(JobParameters params) {
327  StringBuilder sb = new StringBuilder();
328  sb.append("Media content has changed:\n");
329  if (params.getTriggeredContentAuthorities() != null) {
330      sb.append("Authorities: ");
331      boolean first = true;
332      for (String auth :
333          params.getTriggeredContentAuthorities()) {
334          if (first) {
335              first = false;
336          } else {
337             sb.append(", ");
338          }
339           sb.append(auth);
340      }
341      if (params.getTriggeredContentUris() != null) {
342          for (Uri uri : params.getTriggeredContentUris()) {
343              sb.append("\n");
344              sb.append(uri);
345          }
346      }
347  } else {
348      sb.append("(No content)");
349  }
350  Log.i(TAG, sb.toString());
351  return true;
352}
353</pre>
354
355<h2 id="further-optimization">
356  Further Optimizing Your App
357</h2>
358
359<p>
360  Optimizing your apps to run on low-memory devices, or in low-memory
361  conditions, can improve performance and user experience. Removing
362  dependencies on background services and statically-registered implicit
363  broadcast receivers can help your app run better on such devices. Although
364  Android N takes steps to reduce some of these issues, it is
365  recommended that you optimize your app to run without the use of these
366  background processes entirely.
367</p>
368
369<p>
370  Android N introduces some additional <a href=
371  "{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a> commands that
372  you can use to test app behavior with those background processes disabled:
373</p>
374
375<ul>
376  <li>To simulate conditions where implicit broadcasts and background services
377  are unavailable, enter the following command:
378  </li>
379
380  <li style="list-style: none; display: inline">
381<pre class="no-pretty-print">
382{@code $ adb shell cmd appops set &lt;package_name&gt; RUN_IN_BACKGROUND ignore}
383</pre>
384  </li>
385
386  <li>To re-enable implicit broadcasts and background services, enter the
387  following command:
388  </li>
389
390  <li style="list-style: none; display: inline">
391<pre class="no-pretty-print">
392{@code $ adb shell cmd appops set &lt;package_name&gt; RUN_IN_BACKGROUND allow}
393</pre>
394  </li>
395</ul>
396