Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba321c8f authored by David Friedman's avatar David Friedman Committed by Android (Google) Code Review
Browse files

Merge "Docs: Added Background Check N-Preview Feature page" into mnc-mr-docs

parents 9aad9514 9f2ab4ff
Loading
Loading
Loading
Loading
+426 −0
Original line number Original line Diff line number Diff line
page.title=N Developer Preview Implicit Broadcast Restrictions
page.metaDescription=New restrictions to implicit broadcasts.
page.keywords="android N", "implicit broadcasts", "job scheduler"
@jd:body

<div id="qv-wrapper">
  <div id="qv">
    <h2>
      In this document
    </h2>

    <ol>
      <li>
        <a href="#connectivity-action">Restrictions on CONNECTIVITY_ACTION</a>
      </li>

      <li>
        <a href="#sched-jobs">Scheduling Network Jobs on Unmetered
        Connections</a>
      </li>

      <li>
        <a href="#monitor-conn">Monitoring Network Connectivity While the App
        is Running</a>
      </li>

      <li>
        <a href="#persistant-monitor-conn">Persistent Monitoring of Network
        Connectivity</a>
      </li>

      <li>
        <a href="#media-broadcasts">Restrictions on NEW_PICTURE and
        NEW_VIDEO</a>
      </li>

      <li>
        <a href="#new-jobinfo">New JobInfo methods</a>
      </li>

      <li>
        <a href="#new-jobparam">New JobParameter Methods</a>
      </li>

      <li>
        <a href="#further-optimization">Further Optimizing Your App</a>
      </li>
    </ol>
  </div>
</div>

<p>
  Background processes can be memory and battery intensive. For example,
  Implicit broadcasts frequently start background apps that have registered to
  listen for them. This can have a substantial impact on device performance and
  user experience.
</p>

<p>
  To alleviate this issue, the N Developer Preview applies the following
  restrictions:
</p>

<ul>
  <li>Apps targeting the N Developer Preview will not receive {@link
  android.net.ConnectivityManager#CONNECTIVITY_ACTION} broadcasts if they
  register to receive them in their manifest. Apps running in the foreground
  can still listen for {@code CONNECTIVITY_CHANGE} on their main thread with a
  registered {@link android.content.BroadcastReceiver}.
  </li>

  <li>Apps will not be able to to send or receive {@code NEW_PICTURE} or {@code
  NEW_VIDEO} broadcasts.
  </li>
</ul>

<p>
  The Android framework provides several solutions to mitigate the need for
  these implicit broadcasts. For example, {@link android.app.job.JobScheduler}
  and <a href=
  "https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
  GcmNetworkManager</a> provide robust mechanisms to schedule network
  operations when specified conditions, such as a connection to an unmetered
  network, are met. You can also use {@link android.app.job.JobScheduler} to
  react to changes to content providers. {@link android.app.job.JobInfo}
  objects, built by the {@link android.app.job.JobInfo.Builder JobInfo.Builder}
  class, encapsulate the parameters that {@link android.app.job.JobScheduler}
  uses to schedule your job. When the conditions of the job are met, the system
  executes this job on your app's {@link android.app.job.JobService}.
</p>

<p>
  In this document, we will learn how to use alternative methods, such as
  {@link android.app.job.JobScheduler}, to adapt your app to these new
  restrictions.
</p>

<h2 id="connectivity-action">
  Restrictions on CONNECTIVITY_ACTION
</h2>

<p>
  Apps targeting the N Developer Preview do not receive {@link
  android.net.ConnectivityManager#CONNECTIVITY_ACTION} broadcasts, even if they
  register to receive them in their manifest. This could pose a problem for
  apps that want to listen for network changes or perform bulk network
  activities when the device connects to an unmetered network. Several
  solutions to get around this restriction already exist in the Android
  framework, but choosing the right one depends on what you want your app to
  accomplish.
</p>

<p class="note">
  <strong>Note:</strong> A {@link android.content.BroadcastReceiver} registered with
  {@link android.content.Context#registerReceiver Context.registerReceiver()}
  continues to receive these broadcasts on the app’s main activity thread.
</p>

<h3 id="sched-jobs">
  Scheduling Network Jobs on Unmetered Connections
</h3>

<p>
  When using the {@link android.app.job.JobInfo.Builder JobInfo.Builder} class
  to build your {@link android.app.job.JobInfo} object, apply the {@link
  android.app.job.JobInfo.Builder#setRequiredNetworkType
  setRequiredNetworkType()} method and pass {@link android.app.job.JobInfo
  JobInfo.NETWORK_TYPE_UNMETERED} as a job parameter. The following code sample
  schedules a service when the device connects to an unmetered network and is
  charging:
</p>

<pre>
public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
  JobScheduler js =
      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
  JobInfo job = new JobInfo.Builder(
    MY_BACKGROUND_JOB,
    new ComponentName(context, JobService.class))
      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
      .setRequiresCharging(true)
      .build();
  js.schedule(job);
}
</pre>

<p>
  When the conditions for your job are met, your app receives a callback to run
  the {@link android.app.job.JobService#onStartJob onStartJob()} method in the
  specified {@code JobService.class}. To see more examples of {@link
  android.app.job.JobScheduler} implementation, see the <a href=
  "{@docRoot}samples/JobScheduler/index.html">JobScheduler sample app</a>.
</p>

<p>
Applications that use GMSCore services, and target Android 5.0 (API level 21)
or lower, should use <a href=
"https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
GcmNetworkManager</a> and specify {@code Task.NETWORK_STATE_UNMETERED}.
</p>

<h3 id="monitor-conn">
  Monitoring Network Connectivity While the App is Running
</h3>

<p>
  Apps running in the foreground can still listen for {@code
  CONNECTIVITY_CHANGE} with a registered {@link
  android.content.BroadcastReceiver}. However, the {@link
  android.net.ConnectivityManager} API provides a more robust method to request
  a callback during specified network conditions.
</p>

<p>
  {@link android.net.NetworkRequest} objects define the parameters of the
  network callback in terms of {@link android.net.NetworkCapabilities}. You
  create {@link android.net.NetworkRequest} objects with the {@link
  android.net.NetworkRequest.Builder NetworkRequest.Builder} class. {@link
  android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest,
  android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()}
  then passes the {@link android.net.NetworkRequest} object to the system. When
  the network conditions are met, the app receives a callback to execute the
  {@link android.net.ConnectivityManager.NetworkCallback#onAvailable
  onAvailable()} method defined in its {@link
  android.net.ConnectivityManager.NetworkCallback} class.
</p>

<p>
  The app continues to receive callbacks until either the app exits or it calls
  {@link android.net.ConnectivityManager#unregisterNetworkCallback
  unregisterNetworkCallback()}.
</p>

<h3 id="persistant-monitor-conn">
  Persistent Monitoring of Network Connectivity
</h3>

<p>
  The {@link android.net.ConnectivityManager} API also provides a method to
  persistently monitor network connectivity. Due to its impact on performance,
  however, it should be used with caution.
</p>

<p>
  An app may use {@link
  android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest,
  android.app.PendingIntent) registerNetworkCallback()} to register a {@link
  android.app.PendingIntent} rather than a {@link
  android.net.ConnectivityManager.NetworkCallback}. The request may outlive the
  calling app and require it to start up in order to process a callback.
</p>

<p>
  Before considering this option, think twice about whether this solution is
  actually necessary, and consider the impact to performance and user
  experience when doing so. Only apps that have a real need to start up on a
  network change should implement this solution. Otherwise, every effort should
  be taken to <a href="#connectivity-action">implement the alternatives</a>.
</p>

<h2 id="media-broadcasts">
  Restrictions on NEW_PICTURE and NEW_VIDEO
</h2>

<p>
  In the N Developer Preview, apps are not able to send or receive {@code
  NEW_PICTURE} or {@code NEW_VIDEO} broadcasts. This restriction helps
  alleviate the performance and user experience impacts when several apps must
  wake up in order to process them. The N Developer Preview extends {@link
  android.app.job.JobInfo} and {@link android.app.job.JobParameters} to provide
  an alternative solution.
</p>

<h3 id="new-jobinfo">
  New JobInfo methods
</h3>

<p>
  To help trigger jobs on content URI changes, the N Developer Preview extends
  the {@link android.app.job.JobInfo} API with the following methods:
</p>

<dl>
  <dt>
    {@code JobInfo.TriggerContentUri()}
  </dt>

  <dd>
    Encapsulates parameters required to trigger a job on content URI changes.
  </dd>

  <dt>
    {@code JobInfo.Builder.addTriggerContentUri()}
  </dt>

  <dd>
    Passes a {@code TriggerContentUri} object to {@link
    android.app.job.JobInfo}. The encapsulated content URI is monitored with a
    {@link android.database.ContentObserver}. If there are multiple {@code
    TriggerContentUri} objects associated with a job, the system provides a
    callback even if it reports a change in only one of the content URIs.
  </dd>

  <dd>
    Add the {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} flag to
    trigger the job if any descendants of the given URI change. This flag
    corresponds to the {@code notifyForDescendants} parameter passed to {@link
    android.content.ContentResolver#registerContentObserver
    registerContentObserver()}.
  </dd>
</dl>

<p class="note">
  <strong>Note:</strong> {@code TriggerContentUri()} cannot be used in
  combination with {@link android.app.job.JobInfo.Builder#setPeriodic
  setPeriodic()} or {@link android.app.job.JobInfo.Builder#setPersisted
  setPersisted()}. To continually monitor for content changes, schedule a new
  {@link android.app.job.JobInfo} before the app’s {@link
  android.app.job.JobService} finishes handling the most recent callback.
</p>

<p>
  The following sample code schedules a job to trigger when the system reports
  a change to the content URI, {@code MEDIA_URI}:
</p>

<pre>
public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
  JobScheduler js =
          (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
  JobInfo.Builder builder = new JobInfo.Builder(
          MY_BACKGROUND_JOB,
          new ComponentName(context, MediaContentJob.class));
  builder.addTriggerContentUri(
          new JobInfo.TriggerContentUri(MEDIA_URI,
          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
  js.schedule(builder.build());
}
</pre>
<p>
  When the system reports a change in the specified content URI(s), your app
  receives a callback and a {@link android.app.job.JobParameters} object is
  passed to the {@link android.app.job.JobService#onStartJob onStartJob()}
  method in {@code MediaContentJob.class}.
</p>

<h3 id="new-jobparam">
  New JobParameter Methods
</h3>

<p>
  The N Developer Preview also extends {@link android.app.job.JobParameters} to
  allow your app to receive useful information about what content authorities
  and URIs triggered the job:
</p>

<dl>
  <dt>
    {@code Uri[] getTriggeredContentUris()}
  </dt>

  <dd>
    Returns an array of URIs that have triggered the job. This will be {@code
    null} if either no URIs have triggered the job (for example, the job was
    triggered due to a deadline or some other reason), or the number of changed
    URIs is greater than 50.
  </dd>

  <dt>
    {@code String[] getTriggeredContentAuthorities()}
  </dt>

  <dd>
    Returns a string array of content authorities that have triggered the job.
    If the returned array is not {@code null}, use {@code getTriggeredContentUris()}
    to retrieve the details of which URIs have changed.
  </dd>
</dl>

<p>
  The following sample code overrides the {@link
  android.app.job.JobService#onStartJob JobService.onStartJob()} method and
  records the content authorities and URIs that have triggered the job:
</p>

<pre>
&#64;Override
public boolean onStartJob(JobParameters params) {
  StringBuilder sb = new StringBuilder();
  sb.append("Media content has changed:\n");
  if (params.getTriggeredContentAuthorities() != null) {
      sb.append("Authorities: ");
      boolean first = true;
      for (String auth :
          params.getTriggeredContentAuthorities()) {
          if (first) {
              first = false;
          } else {
             sb.append(", ");
          }
           sb.append(auth);
      }
      if (params.getTriggeredContentUris() != null) {
          for (Uri uri : params.getTriggeredContentUris()) {
              sb.append("\n");
              sb.append(uri);
          }
      }
  } else {
      sb.append("(No content)");
  }
  Log.i(TAG, sb.toString());
  return true;
}
</pre>

<h2 id="further-optimization">
  Further Optimizing Your App
</h2>

<p>
  Optimizing your apps to run on low-memory devices, or in low-memory
  conditions, can improve performance and user experience. Eliminating the use
  of implicit broadcasts and background services is a great way to make sure
  your app runs well on such devices. Although the N Developer Preview takes
  steps to limit the use of certain implicit broadcasts, consider optimizing
  your app to run without the use of implicit broadcasts and background
  services, entirely.</p>

<p>
  To help you test how your app behaves without those background processes, The
  N Developer Preview introduces some additional <a href=
  "{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a> commands:
</p>

<ul>
  <li>To simulate conditions where implicit broadcasts and background services
  are unavailable, enter the following command:
  </li>

  <li style="list-style: none; display: inline">
<pre class="no-pretty-print">
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND ignore}
</pre>
  </li>

  <li>To re-enable implicit broadcasts and background services, enter the
  following command:
  </li>

  <li style="list-style: none; display: inline">
<pre class="no-pretty-print">
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND allow}
</pre>
  </li>
</ul>

<p>
  The Android framework is constantly evolving to help apps run great on a wide
  variety of devices. To learn more and join the discussion, <a href=
  "{@docRoot}">read this blog post!</a>
</p>
 No newline at end of file