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@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 <package_name> 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 <package_name> RUN_IN_BACKGROUND allow} 393</pre> 394 </li> 395</ul> 396