Optimalisasi Latar Belakang di Android Nougat!

Proses latar belakang bisa menguras memori dan baterai. Misalnya, sebuah siaran implisit dapat memulai banyak proses latar belakang yang telah didaftarkan untuk mendengarkannya, sekalipun proses-proses itu mungkin tidak melakukan banyak pekerjaan. Hal ini bisa berdampak besar pada kinerja perangkat dan pengalaman pengguna.

Untuk meringankan masalah ini, Android N menerapkan pembatasan berikut:

  • Aplikasi yang menargetkan Pratinjau tidak menerima siaran CONNECTIVITY_ACTION jika mereka mendaftar untuk menerimanya dalam manifes mereka. Aplikasi yang berjalan tetap bisa mendengarkan CONNECTIVITY_CHANGE pada thread utama mereka dengan mendaftarkan BroadcastReceiver pada Context.registerReceiver().
  • Aplikasi tidak bisa mengirim atau menerima siaran ACTION_NEW_PICTURE atau ACTION_NEW_VIDEO. Optimalisasi ini memengaruhi semua aplikasi, tidak hanya aplikasi yang menargetkan Pratinjau.

Jika aplikasi Anda menggunakan intent ini, Anda harus membuang dependensi padanya secepat mungkin agar Anda bisa menargetkan perangkat Android N dengan benar. Kerangka kerja Android menyediakan beberapa solusi untuk mengurangi kebutuhan akan siaran implisit ini. Misalnya, JobScheduler danGcmNetworkManager menyediakan mekanisme yang tangguh untuk menjadwalkan operasi jaringan bila kondisi yang ditetapkan, seperti koneksi ke jaringan berbiaya tetap, terpenuhi. Anda sekarang juga bisa menggunakan JobScheduler untuk bereaksi terhadap perubahan penyedia materi. Objek JobInfo membungkus parameter yang digunakan JobScheduler untuk menjadwalkan pekerjaan Anda. Bila syarat-syarat pekerjaan sudah terpenuhi, sistem akan mengeksekusi pekerjaan ini pada JobService aplikasi Anda.

Dalam dokumen ini, kita akan mempelajari cara menggunakan metode alternatif, seperti JobScheduler, untuk menyesuaikan aplikasi Anda dengan pembatasan yang baru.

Pembatasan pada CONNECTIVITY_ACTION

Aplikasi yang menargetkan Android N tidak menerima siaran CONNECTIVITY_ACTION jika mereka mendaftar untuk menerimanya dalam manifes mereka, dan proses yang bergantung pada siaran ini tidak akan dimulai. Hal ini bisa menimbulkan masalah bagi aplikasi yang ingin memantau perubahan jaringan atau melakukan aktivitas jaringan dalam jumlah besar bila perangkat menghubungkan ke jaringan berbiaya tetap. Beberapa solusi untuk menyiasati pembatasan ini sudah ada dalam kerangka kerja Android, namun pemilihan solusi yang tepat bergantung pada apa yang ingin dicapai oleh aplikasi Anda.

Catatan: Sebuah BroadcastReceiver yang mendaftar pada Context.registerReceiver() akan terus menerima siaran ini saat aplikasi berjalan.

Menjadwalkan Pekerjaan Jaringan pada Koneksi Berbiaya Tetap

Saat menggunakan kelas JobInfo.Builder untuk membangun objek JobInfo Anda, terapkan metode setRequiredNetworkType() dan teruskan JobInfo.NETWORK_TYPE_UNMETERED sebagai parameter pekerjaan. Contoh kode berikut menjadwalkan layanan yang akan dijalankan ketika perangkat terhubung ke jaringan berbiaya tetap dan dikenai biaya:

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, MyJobService.class))
      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
      .setRequiresCharging(true)
      .build();
  js.schedule(job);
}

Bila syarat untuk pekerjaan Anda terpenuhi, aplikasi Anda akan menerima callback untuk menjalankan metode onStartJob() dalamJobService.class yang ditetapkan. Untuk melihat contoh selengkapnya mengenai implementasi JobScheduler, lihat aplikasi contoh JobScheduler.

Aplikasi yang menggunakan layanan GMSCore, dan menargetkan Android 5.0 (API level 21) atau yang lebih rendah, bisa menggunakan GcmNetworkManager dan menetapkan Task.NETWORK_STATE_UNMETERED.

Memantau Konektivitas Jaringan Saat Aplikasi Dijalankan

Aplikasi yang berjalan tetap bisa memantau CONNECTIVITY_CHANGE dengan BroadcastReceiver yang telah didaftarkan. Akan tetapi, ConnectivityManager API menyediakan metode yang lebih tangguh untuk meminta callback hanya bila persyaratan jaringan yang ditetapkan terpenuhi.

Objek NetworkRequest mendefinisikan parameter callback jaringan dari segi NetworkCapabilities. Anda membuat objek NetworkRequest dengan kelas NetworkRequest.Builder. registerNetworkCallback() kemudian meneruskan objek NetworkRequest ke sistem. Bila syarat jaringan terpenuhi, aplikasi akan menerima callback untuk mengeksekusi metode onAvailable() yang didefinisikan dalam kelas ConnectivityManager.NetworkCallback.

Aplikasi akan terus menerima callback hingga aplikasi keluar atau memanggil unregisterNetworkCallback().

Pembatasan pada NEW_PICTURE dan NEW_VIDEO

Di Android N, aplikasi tidak bisa mengirim atau menerima siaran ACTION_NEW_PICTURE atau ACTION_NEW_VIDEO. Pembatasan ini membantu meringankan dampak terhadap kinerja dan pengalaman pengguna bila beberapa aplikasi harus aktif untuk memproses gambar atau video baru. Android N memperluas JobInfo dan JobParameters untuk menyediakan solusi alternatif.

Metode JobInfo baru

Untuk memicu pekerjaan saat perubahan URI materi, Android N memperluas JobInfo API dengan metode berikut:

JobInfo.TriggerContentUri()
Membungkus parameter yang diperlukan untuk memicu pekerjaan saat perubahan URI materi.
JobInfo.Builder.addTriggerContentUri()
Meneruskan objek TriggerContentUri ke JobInfo. Sebuah ContentObserver akan memantau URI materi yang dibungkus. Jika terdapat beberapa objek TriggerContentUri yang berhubungan dengan pekerjaan, sistem memberikan sebuah callback bahkan jika itu hanya melaporkan perubahan pada salah satu URI materi.
Tambahkan flag TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS untuk memicu pekerjaan jika ada turunan dari perubahan URI yang diberikan. Flag ini berkaitan dengan parameter notifyForDescendants yang diteruskan ke registerContentObserver().

Catatan: TriggerContentUri() tidak bisa digunakan bersama-sama dengan setPeriodic() atau setPersisted(). Untuk terus memantau perubahan materi, jadwalkan JobInfo baru sebelum JobService aplikasi selesai menangani callback terbaru.

Kode contoh berikut menjadwalkan pekerjaan yang akan dipicu bila sistem melaporkan perubahan ke URI materi, MEDIA_URI:

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(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
  js.schedule(builder.build());
}

Bila sistem melaporkan perubahan dalam URI materi yang ditetapkan, aplikasi Anda akan menerima callback dan objek JobParameters akan diteruskan ke metode onStartJob() dalam MediaContentJob.class.

Metode JobParameter Baru

Android N juga memperluas JobParameters untuk memungkinkan aplikasi Anda menerima informasi yang berguna tentang otoritas materi dan URI yang memicu pekerjaan:

Uri[] getTriggeredContentUris()
Mengembalikan larik URL yang telah memicu pekerjaan. Ini akan berupa null jika tidak ada URI yang memicu pekerjaan (misalnya, pekerjaan dipicu karena batas waktu atau alasan lainnya), atau jumlah URI yang berubah lebih dari 50.
String[] getTriggeredContentAuthorities()
Mengembalikan larik string otoritas materi yang telah memicu pekerjaan. Jika larik yang dikembalikan bukan null, gunakan getTriggeredContentUris() untuk mengambil detail URI yang telah berubah.

Kode contoh berikut mengganti metode JobService.onStartJob() dan mencatat otoritas materi serta URI yang telah memicu pekerjaan:

@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;
}

Leave a Reply

Your email address will not be published. Required fields are marked *