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