8.3: Job Scheduler

Daftar Isi:

Anda sudah melihat bahwa Anda bisa memicu acara berdasarkan jam real-time atau waktu yang sudah lewat sejak booting menggunakan kelas AlarmManager. Namun sebagian besar tugas tidak memerlukan waktu tepat, tetapi harus dijadwalkan berdasarkan kombinasi sistem dan persyaratan pengguna. Misalnya, aplikasi berita mungkin memperbarui berita di pagi hari, tetapi dapat menunggu sampai perangkat diisi daya dan dihubungkan ke wifi untuk memperbarui berita, untuk mempertahankan data pengguna dan sumber daya sistem.

Kelas JobScheduler ditujukan untuk penjadwalan seperti ini; kelas ini mengizinkan Anda menyetel kondisi, atau parameter menjalankan tugas. Berdasarkan kondisi ini, JobScheduler menghitung waktu terbaik untuk menjadwalkan eksekusi pekerjaan. Beberapa contoh parameter ini adalah: persistensi pekerjaan di semua boot ulang, interval yang harus dijalankan pekerjaan, terlepas dari apakah perangkat dicolokkan ke arus listrik atau tidak, atau apakah perangkat tersebut sedang idle atau tidak.

Tugas yang akan dijalankan diimplementasikan sebagai subkelas JobService dan dieksekusi berdasarkan batasan yang telah ditentukan.

JobScheduler hanya tersedia pada perangkat yang menjalankan API 21+ dan saat ini tidak tersedia dalam pustaka dukungan. Untuk kompatibilitas mundur, gunakan GcmNetworkManager (akan segera menjadi FirebaseJobDispatcher).

Dalam praktik ini Anda akan membuat aplikasi yang menjadwalkan notifikasi untuk diposkan saat parameter disetel oleh pengguna terpenuhi, dan persyaratan sistemnya dipenuhi.

Yang harus sudah Anda KETAHUI

Dari praktik sebelumnya, Anda harus sudah bisa:

  • Mengirimkan notifikasi.
  • Mendapatkan nilai integer dari tampilan Spinner.
  • Menggunakan tampilan Switch untuk masukan pengguna.
  • Membuat PendingIntent.

Yang akan Anda PELAJARI

Anda akan belajar:

  • Mengimplementasikan JobService.
  • Membuat objek JobInfo dengan batasan spesifik.
  • Menjadwalkan JobService berdasarkan objek JobInfo.

Yang akan Anda LAKUKAN

Dalam praktik ini Anda akan:

  • Mengimplementasikan JobService yang mengirimkan notifikasi sederhana untuk memberi tahu pengguna bahwa pekerjaan sedang berjalan.
  • Mendapatkan masukan pengguna untuk mengonfigurasi batasan (seperti menunggu sampai perangkat diisi daya) di JobService yang Anda jadwalkan.
  • Menjadwalkan pekerjaan menggunakan JobScheduler.

Ringkasan Aplikasi

Dalam praktik ini Anda akan membuat aplikasi bernama "Notification Scheduler". Aplikasi akan mendemonstrasikan framework JobScheduler dengan mengizinkan pengguna untuk memilih batasan dan menjadwalkan pekerjaan. Saat pekerjaan dieksekusi, notifikasi akan diposkan (dalam aplikasi ini, notifikasi secara efektif adalah "pekerjaan" Anda). Pratinjau untuk Penjadwal Notifikasi

Untuk menggunakan JobScheduler, Anda memerlukan dua bagian tambahan: JobService dan JobInfo. Objek JobInfo berisi serangkaian kondisi yang akan memicu pekerjaan untuk berjalan. JobService adalah implementasi pekerjaan yang akan dijalankan di bawah kondisi tersebut.

Tugas 1. Mengimplementasikan JobService

Pertama, Anda harus membuat layanan yang akan dijalankan pada waktu yang ditetapkan oleh kondisi. JobService secara otomatis dieksekusi oleh sistem, dan bagian yang perlu Anda implementasikan adalah:

callback onStartJob()

  • dipanggil saat sistem menentukan bahwa tugas harus dijalankan. Anda mengimplementasikan pekerjaan untuk dikerjakan dalam metode ini.
    Catatan: onStartJob() dieksekusi pada thread utama, sehingga tugas yang berjalan lama harus diturunkan ke thread yang lain. Dalam hal ini, Anda hanya perlu mengeposkan notifikasi, yang bisa dilakukan dengan aman pada thread utama.
  • mengembalikan boolean yang menunjukkan apakah pekerjaan perlu diteruskan pada thread yang terpisah. Jika benar, pekerjaan diturunkan ke thread yang berbeda dan aplikasi harus memanggil jobFinished() secara eksplisit dalam thread untuk menunjukkan bahwa pekerjaan sudah selesai. Jika nilai pengembaliannya adalah salah, framework tahu bahwa pekerjaan sudah diselesaikan di akhir onStartJob() dan secara otomatis akan memanggil jobFinished() atas nama Anda.

callback onStopJob()

  • dipanggil jika kondisi tidak terpenuhi, yang berarti pekerjaan harus dihentikan.
  • mengembalikan boolean yang menentukan apa yang harus dilakukan jika pekerjaan tidak selesai. Jika nilai pengembaliannya true, pekerjaan akan dijadwalkan ulang, atau akan dibatalkan.

1.1 Membuat Proyek dan NotificationJobService

Verifikasi bahwa SDK minimum yang Anda gunakan adalah API 21. Sebelum API 21, JobScheduler tidak berfungsi, karena kekurangan beberapa API yang diperlukan.

  1. Gunakan template kosong, dan buat proyek baru bernama "Notification Scheduler".
  2. Buat kelas baru bernama NotificationJobService yang memperluas JobService.
  3. Tambahkan metode yang diperlukan: onStartJob() dan onStopJob().
  4. Dalam file AndroidManfiest.xml, daftarkan JobService dengan izin berikut dalam tag <application>:
    <service
       android:name=".NotificationJobService"
       android:permission="android.permission.BIND_JOB_SERVICE"/>
    

1.2 Mengimplementasikan onStartJob()

  1. Tambahkan ikon notifikasi untuk notifikasi "Job Running".
  2. Dalam onStartJob(), buat PendingIntent untuk meluncurkan MainActivity aplikasi untuk digunakan sebagai intent konten untuk notifikasi Anda.
  3. Dalam onStartJob(), konstruksi dan kirimkan notifikasi dengan atribut berikut:

    Atribut

    Judul

    Content Title

    "Job Service"

    Content Text

    "Your Job is running!"

    Content Intent

    contentPendingIntent

    Small Icon

    R.drawable.ic_job_running

    Priority

    NotificationCompat.PRIORITY_HIGH

    Defaults

    NotificationCompat.DEFAULT_ALL

    AutoCancel

    true

  4. Pastikan onStartJob() mengembalikan false, karena semua pekerjaan diselesaikan dalam callback itu.
  5. Buat onStopJob() mengembalikan true, agar pekerjaan dijadwalkan ulang jika gagal.
@Override
public boolean onStartJob(JobParameters jobParameters) {
   //Set up the notification content intent to launch the app when clicked
   PendingIntent contentPendingIntent = PendingIntent.getActivity
           (this, 0, new Intent(this, MainActivity.class),
            PendingIntent.FLAG_UPDATE_CURRENT);

   NotificationManager manager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setContentTitle(getString(R.string.job_service))
           .setContentText(getString(R.string.job_running))
           .setContentIntent(contentPendingIntent)
           .setSmallIcon(R.drawable.ic_job_running)
           .setPriority(NotificationCompat.PRIORITY_HIGH)
           .setDefaults(NotificationCompat.DEFAULT_ALL)
           .setAutoCancel(true);

   manager.notify(0, builder.build());

   return false;
}

Tugas 2. Mengimplementasikan kondisi kerja

Sekarang karena Anda telah memiliki JobService, ini saatnya mengidentifikasi kriteria untuk menjalankan pekerjaan. Untuk ini, gunakan komponen JobInfo. Anda akan membuat serangkaian kondisi berparameter untuk menjalankan pekerjaan menggunakan berbagai tipe konektivitas jaringan dan status perangkat.

Pertama-tama, Anda akan membuat grup tombol radio untuk menentukan jenis jaringan yang diperlukan untuk pekerjaan ini.

2.1 Mengimplementasikan batasan jaringan

Salah satu dari kondisi yang memungkinkan untuk menjalankan pekerjaan adalah status konektivitas jaringan. Anda bisa membatasi JobService untuk dieksekusi hanya ketika kondisi jaringan tertentu dipenuhi. Opsinya adalah:

  • NETWORK_TYPE_NONE: pekerjaan akan berjalan dengan atau tanpa koneksi jaringan. Ini adalah nilai default-nya.
  • NETWORK_TYPE_ANY: pekerjaan akan berjalan selama jaringan (seluler, wifi) tersedia.
  • NETWORK_TYPE_UNMETERED: pekerjaan akan berjalan selama perangkat terhubung ke wifi yang tidak menggunakan HotSpot.

Buat layout untuk aplikasi

Buat layout untuk aplikasi untuk menunjukkan tombol yang bisa dipakai pengguna untuk memilih kriteria jaringan. UI untuk Kontrol Kondisi Jaringan

  1. Dalam file activity_main.xml, ubah elemen rootview ke LinearLayout vertical.
  2. Ubah TextView agar memiliki atribut berikut:

    Atribut

    Nilai

    android:layout_width

    "wrap_content"

    android:layout_height

    "wrap_content"

    android:text

    "Network Type Required: "

    android:textAppearance

    "@style/TextAppearance.AppCompat.Subhead"

    android:layout_margin

    "4dp"

  3. Tambahkan elemen kontainer RadioGroup di bawah TextView dengan atribut berikut:

    Atribut

    Nilai

    android:layout_width

    "wrap_content"

    android:layout_height

    "wrap_content"

    android:orientation

    "horizontal"

    android:id

    "@+id/networkOptions"

    android:layout_margin

    "4dp"

    Catatan: Menggunakan radio memastikan bahwa hanya satu dari anaknya yang dapat pilih pada satu waktu. Untuk informasi selengkapnya tentang Tombol Radio, lihat panduan ini.
  4. Tambahkan tiga RadioButton sebagai anak ke RadioGroup dengan tinggi dan lebar layout yang disetel ke "wrap_content" dan atribut berikut ini:

    RadioButton 1

    android:text

    "None"

    android:id

    "@+id/noNetwork"

    android:checked

    true

    RadioButton 2

    android:text

    "Any"

    android:id

    "@+id/anyNetwork"

    RadioButton 3

    android:text

    "Wifi"

    android:id

    "@+id/wifiNetwork"

  5. Tambahkan dua tombol di bawa grup tombol radio dengan tinggi dan lebar yang disetel ke "wrap_content" dengan atribut berikut ini:

    Button 1

    android:text

    "Schedule Job"

    android:onClick

    "scheduleJob"

    android:layout_gravity

    "center_horizontal"

    android:layout_margin

    "4dp"

    Button 2

    android:text

    "Cancel Jobs"

    android:onClick

    "cancelJobs"

    android:layout_gravity

    "center_horizontal"

    android:layout_margin

    "4dp"

  6. Tambahkan stub metode untuk kedua metode onClick() di MainActivity.

Dapatkan opsi jaringan pilihan

  1. Dalam scheduleJob(), temukan RadioGroup menurut id dan simpan dalam variabel instance bernama networkOptions.
  2. Dapatkan id jaringan pilihan dan simpan dalam variabel integer:
    int selectedNetworkID = networkOptions.getCheckedRadioButtonId();
    
  3. Buat variabel integer opsi jaringan pilihan dan setel agar setara dengan opsi jaringan default (jaringan tidak diperlukan):
    int selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE;
    
  4. Buat pernyataan switch dengan id jaringan pilihan, dan tambahkan kasus untuk setiap id yang mungkin:
    switch(selectedNetworkID){
        case R.id.noNetwork:
            break;   
        case R.id.anyNetwork:
            break;
        case R.id.wifiNetwork:
            break;
    }
    
  5. Tetapkan opsi jaringan pilihan ke konstanta jaringan JobInfo yang sesuai, tergantung kasusnya:
    switch(selectedNetworkID){
       case R.id.noNetwork:
           selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE;
           break;
       case R.id.anyNetwork:
           selectedNetworkOption = JobInfo.NETWORK_TYPE_ANY;
           break;
       case R.id.wifiNetwork:
           selectedNetworkOption = JobInfo.NETWORK_TYPE_UNMETERED;
           break;
    }
    

Buat JobScheduler dan objek JobInfo

  1. Dalam MainActivity, buat variabel anggota untuk JobScheduler, dan inisialisasikan di scheduleJob() menggunakan getSystemService():
    mScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
    
  2. Buat konstanta anggota untuk JOB_ID, dan setel agar setara dengan 0.
  3. Buat objek JobInfo.Builder dalam scheduleJob(). Konsruktor untuk kelas JobInfo.Builder memerlukan dua parameter:
    • JOB_ID.
    • ComponentName untuk JobService yang Anda buat. ComponentName digunakan untuk mengidentifikasi JobService dengan objek JobInfo.
      ComponentName serviceName = new ComponentName(getPackageName(),
      NotificationJobService.class.getName());
      JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceName)
      
  4. Panggil setRequiredNetworkType() pada objek JobInfo.Builder, meneruskan opsi jaringan pilihan:
    .setRequiredNetworkType(selectedNetworkOption);
    
  5. Panggil schedule() pada objek JobScheduler, meneruskan objek JobInfo dengan metode build():
    JobInfo myJobInfo = builder.build();
    mScheduler.schedule(myJobInfo);
    
  6. Tampilkan pesan Toast, beri tahu pengguna bahwa pekerjaan dijadwalkan.
  7. Dalam metode cancelJobs(), periksa apakah objek JobScheduler adalah null, dan jika tidak, panggil cancelAll() pada metode untuk menghapus semua pekerjaan yang tertunda, setel ulang JobScheduler ke null, dan tampilkan pesan Toast untuk memberi tahu pengguna bahwa pekerjaan dibatalkan:
    if (mScheduler!=null){
       mScheduler.cancelAll();
       mScheduler = null;
       Toast.makeText(this, "Jobs Canceled", Toast.LENGTH_SHORT).show();
    }
    
  8. Jalankan aplikasi. Anda sekarang bisa menyetel tugas yang memiliki keterbatasan jaringan dan melihat berapa lama waktu yang dibutuhkan untuk dieksekusi. Dalam hal ini, tugasnya adalah mengirimkan notifikasi. Untuk menghilangkan notifikasi, gesek layar atau ketuk untuk membuka notifikasi.

Anda mungkin melihat bahwa jika Anda tidak mengubah batasan jaringan ke "Any" atau "Wifi", aplikasi akan crash dengan pengecualian berikut ini:

java.lang.IllegalArgumentException:
   You're trying to build a job with no constraints, this is not allowed.

Ini karena kondisi "No Network Required" adalah default-nya dan sebenarnya tidak dihitung sebagai batasan. JobScheduler membutuhkan paling tidak satu batasan untuk menjadwalkan JobService dengan benar. Dalam bagian ini Anda akan membuat ketentuan yaitu true saat paling tidak satu batasan disetel, dan false jika tidak. Lalu Anda perlu menjadwalkan tugas jika true, dan tampilkan Toast untuk memberi tahu pengguna untuk menyetel batasan jika tidak.

2.2 Memeriksa batasan

JobScheduler memerlukan paling tidak satu batasan untuk disetel. Dalam tugas ini Anda akan membuat boolean yang akan melacak apakah persyaratan ini sudah dipenuhi, jadi Anda bisa memberi tahu pengguna untuk menyetel paling tidak satu batasan jika mereka belum melakukannya. Saat membuat opsi tambahan pada langkah-langkah berikutnya, Anda perlu memodifikasi boolean ini agar selalu true jika paling tidak salah satu batasan disetel dan false jika tidak.

  1. Buat variabel boolean bernama constraintSet yang true jika opsi jaringan pilihannya bukan default JobInfo.NETWORK_TYPE_NONE:
    boolean constraintSet = selectedNetworkOption != JobInfo.NETWORK_TYPE_NONE;
    
  2. Buat blok if/else menggunakan boolean constraintSet.
  3. Pindahkan kode yang menjadwalkan tugas dan menampilkan pesan Toast ke dalam blok if.
  4. Jika constraintSet adalah false, tampilkan pesan Toast ke pengguna untuk menyetel paling tidak satu batasan. Jangan lupa untuk mengekstrak sumber daya string:
    if(constraintSet) {
       //Schedule the job and notify the user
       JobInfo myJobInfo = builder.build();
       mScheduler.schedule(myJobInfo);
       Toast.makeText(this, R.string.job_scheduled, Toast.LENGTH_SHORT).show();
    } else {
       Toast.makeText(this, R.string.no_constraint_toast, Toast.LENGTH_SHORT).show();
    }
    

2.3 Mengimplementasikan batasan Device Idle dan Device Charging

JobScheduler menyertakan kemampuan untuk menunggu hingga perangkat diisi dayanya atau dalam status idle (layar dinonaktifkan dan CPU telah tertidur) untuk mengeksekusi JobService. Anda sekarang akan menambahkan switch ke aplikasi untuk mengganti batasan ini pada JobService. Menambahkan elemen UI untuk batasan baru Kontrol UI untuk opsi Device Idle dan Device Charging

  1. Dalam file activity_main.xml, salin TextView label jenis jaringan dan salin di bawah RadioGroup.
  2. Ubah atribut android:text ke "Requires:".
  3. Di bawah textview ini, sisipkan LinearLayout horizontal dengan margin 4dp.
  4. Buat dua tampilan Switch sebagai anak bagi LinearLayout horizontal dengan tinggi dan lebar yang disetel ke "wrap_content" dan atribut berikut ini:

    Switch 1

    android:text

    "Device Idle"

    android:id

    "@+id/idleSwitch"

    Switch 2

    android:text

    "Device Charging"

    android:id

    "@+id/chargingSwitch"

Tambahkan kode untuk batasan baru

  1. Dalam MainActivity, buat variabel anggota, mDeviceIdle dan mDeviceCharging, untuk switch dan inisialisasikan switch di onCreate().
  2. Dalam metode scheduleJob(), tambahkan panggilan berikut untuk menyetel batasan pada JobScheduler berdasarkan pilihan pengguna dalam switch:
    builder.setRequiresDeviceIdle(mDeviceIdle.isChecked());
    builder.setRequiresCharging(mDeviceCharging.isChecked());
    
  3. Perbarui kode yang menyetel constraintSet untuk mempertimbangkan batasan baru ini:
    boolean constraintSet = (selectedNetworkOption != JobInfo.NETWORK_TYPE_NONE)
       || mDeviceChargingSwitch.isChecked() || mDeviceIdleSwitch.isChecked();
    
  4. Jalankan aplikasi, sekarang dengan batasan tambahan. Coba kombinasi perbedaan switch untuk melihat saat notifikasi dikirimkan (yang menandakan bahwa pekerjaan dijalankan). Anda bisa menguji batasan status pengisian daya dalam emulator dengan membuka menu (ikon elips di sebelah perangkat yang diemulasi), buka panel Battery dan alihkan menu tarik turun Battery Status. Tidak ada cara untuk menyetel emulator dalam mode Idle secara manual saat praktik ini ditulis.

Menunggu sampai perangkat berada dalam mode idle dan dicolokkan adalah pola umum untuk tugas yang menguras baterai seperti mengunduh atau mengunggah file besar.

2.4 Mengimplementasikan batasan Batas Waktu Pengganti

Sampai tahap ini, tidak ada cara untuk dengan tepat mengetahui kapan framework akan mengeksekusi tugas. Sistem memperhitungkan manajemen sumber daya efektif yang mungkin menunda tugas Anda tergantung pada status perangkat, dan tidak menjamin bahwa tugas akan berjalan tepat waktu. Misalnya, aplikasi berita baru mungkin ingin mengunduh berita terbaru hanya ketika wifi tersedia dan perangkat dicolokkan dan diisi dayanya; tetapi pengguna bisa tidak sengaja lupa mengaktifkan wifi atau mengisi daya perangkat. Jika Anda tidak menambahkan parameter waktu ke pekerjaan terjadwal, pengguna tersebut akan kecewa jika mereka membaca berita kemarin saat terbangun di pagi hari. Untuk alasan ini, API JobScheduler menyertakan kemampuan untuk menetapkan batas waktu keras yang akan mengganti batasan sebelumnya. Tambahkan UI baru untuk menyetel batas waktu menjalankan tugas Kontrol UI untuk Kondisi Batas Waktu Pengganti

Dalam langkah ini Anda akan menggunakan komponen UI baru, Seekbar, untuk mengizinkan pengguna menyetel batas waktu antara 0 hingga 100 detik untuk mengeksekusi tugas.

Pengguna menyetel nilai dengan menyeret SeekBar.

  1. Buat LinearLayout horizontal di bawah LinearLayout yang ada dengan switch-nya, yang akan berisi label untuk SeekBar.
  2. SeekBar akan memiliki dua label: label statis seperti label untuk RadioGroup tombol, dan label dinamis yang akan diperbarui dengan nilai dari SeekBar. Tambahkan dua TextView ke LinearLayout dengan atribut berikut ini:

    TextView 1

    android:layout_width

    "wrap_content"

    android:layout_height

    "wrap_content"

    android:text

    "Override Deadline: "

    android:id

    "@+id/seekBarLabel"

    android:textAppearance

    "@style/TextAppearance.AppCompat.Subhead"

    TextView 2

    android:layout_width

    "wrap_content"

    android:layout_height

    "wrap_content"

    android:text

    "Not Set"

    android:id

    "@+id/seekBarProgress"

    android:textAppearance

    "@style/TextAppearance.AppCompat.Subhead"

  3. Tambahkan tampilan SeekBar di bawah LinearLayout dengan atribut berikut ini:

    Atribut

    Nilai

    android:layout_width

    "match_parent"

    android:layout_height

    "wrap_content"

    android:id

    "@+id/seekBar"

    android:layout_margin

    "4dp"

Tulis kode untuk menambahkan batas waktu

  1. Dalam MainActivity, buat variabel anggota untuk SeekBar dan inisialisasikan di onCreate():
    mSeekBar = (SeekBar) findViewById(R.id.seekBar);
    
  2. Buat variabel akhir untuk kedua TextView (yang akan diakses dari kelas bagian dalam) dan inisialisasikan di onCreate():
    final TextView label = (TextView) findViewById(R.id.seekBarLabel);
    final TextView seekBarProgress = (TextView) findViewById(R.id.seekBarProgress);
    
  3. Dalam onCreate(), panggil setOnSeekBarChangeListener() di SeekBar, yang meneruskan OnSeekBarChangeListener baru (Android Studio harus membuat metode yang diperlukan):

    mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
       @Override
       public void onProgressChanged(SeekBar seekBar, int i, boolean b) {}
    
       @Override
       public void onStartTrackingTouch(SeekBar seekBar) {}
    
       @Override
       public void onStopTrackingTouch(SeekBar seekBar) {}
    });
    
  4. Argumen kedua onProgressChanged() adalah nilai saat ini dari SeekBar. Dalam callback onProgressChanged(), periksa apakah nilai integer lebih besar dari 0 (berarti nilai telah ditetapkan oleh pengguna), dan jika iya, setel label kemajuan SeekBar ke nilai integer, yang diikuti dengan "s" untuk menunjukkan detik:
    if (i > 0){
        mSeekBarProgress.setText(String.valueOf(i) + " s");
    }
    
  5. Jika tidak, setel TextView agar terlihat sebagai "Not Set":
    else {
        mSeekBarProgress.setText("Not Set");
    }
    
  6. Batas waktu pengganti seharusnya hanya disetel jika nilai integer SeekBar lebih besar dari 0. Dalam metode scheduleJob(), buat integer untuk menyimpan kemajuan SeekBar dan variabel boolean yang true jika SeekBar memiliki nilai integer yang lebih besar dari 0:
    int seekBarInteger = mSeekBar.getProgress();
    boolean seekBarSet = seekBarInteger > 0;
    
  7. Jika boolean ini true, panggil setOverrideDeadline() pada JobInfo.Builder, yang meneruskan nilai integer dari SeekBar dikalikan 1000 (parameter dalam milidetik, Anda menginginkan agar pengguna menyetel batas waktu dalam detik):
    if (seekBarSet) {
          builder.setOverrideDeadline(seekBarInteger * 1000);
    }
    
  8. Modifikasi boolean constraintSet untuk menyertakan nilai seekBarSet sebagai kemungkinan batasan:
    boolean constraintSet = selectedNetworkOption != JobInfo.NETWORK_TYPE_NONE
       || mDeviceChargingSwitch.isChecked() || mDeviceIdleSwitch.isChecked()
       || seekBarSet;
    
  9. Jalankan aplikasi. Pengguna sekarang bisa menyetel batas waktu tegas dalam detik saat JobService harus dijalankan!

2.5 Mengimplementasikan batasan Periodik

JobScheduler juga mengizinkan Anda menjadwalkan tugas berulang, seperti AlarmManager. Opsi ini memiliki beberapa kekurangan:

  • Tugas tidak dijamin berjalan dalam periode yang ditentukan (kondisi lain mungkin tidak terpenuhi, atau sumber daya sistem tidak cukup).
  • Menggunakan batasan ini mencegah Anda juga menyetel batas waktu pengganti atau latensi () minimun, karena opsi ini tidak masuk akal untuk tugas yang berulang. Lihat dokumentasi JobInfo.Builder) untuk informasi selengkapnya.

Tambahkan Periodic Switch ke layout

Anda akan menambahkan Switch untuk mengizinkan pengguna untuk berpindah-pindah antara menjalankan tugas sekali atau secara berulang-ulang pada interval periodik.

  1. Dalam activity_main.xml, tambahkan tampilan Switch di antara dua LinearLayout horizontal. Gunakan atribut-atribut berikut:

    Atribut

    Nilai

    android:layout_width

    "wrap_content"

    android:layout_height

    "wrap_content"

    android:text

    "Periodic"

    android:id

    "@+id/periodicSwitch"

    android:layout_margin

    "4dp"

  2. Buat variabel anggota untuk switch dan inisialisasikan di onCreate():
    mPeriodicSwitch = (Switch) findViewById(R.id.periodicSwitch);
    

Buat kode untuk menggunakan Periodic Switch

Deadline pengganti dan batasan periodik biasanya saling eksklusif. Anda akan menggunakan switch tersebut untuk berpindah antara fungsionalitas dan label SeekBar untuk mewakili batas waktu pengganti atau interval periodik.

  1. Panggil setOnCheckedChangeListener() pada switch periodik, yang meneruskan OnCheckedChangeListener baru.
  2. Jika dicentang, setel label ke "Periodic Interval: ", jika tidak, ke "Override Deadline: ":
    mPeriodicSwitch.setOnCheckedChangeListener(
       new CompoundButton.OnCheckedChangeListener() {
       @Override
       public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
           if (isChecked){
               label.setText(R.string.periodic_interval);
           } else {
               label.setText(R.string.override_deadline);
           }
       }
    });
    

Yang tersisa sekarang adalah mengimplementasikan logika dalam metode scheduleJob() untuk menyetel batasan pada objek JobInfo dengan benar.

Jika opsi periodiknya adalah on:

  • Jika SeekBar memiliki nilai non-zero, setel batasan dengan memanggil setPeriodic() pada objek JobInfo.Builder.
  • Jika SeekBar memiliki nilai 0, tampilkan pesan Toast yang meminta pengguna untuk menyetel interval periodik dengan SeekBar.

Jika opsi periodiknya adalah off:

  • Jika SeekBar memiliki nilai selain nol, pengguna telah menyetel batas waktu pengganti. Aplikasikan batas waktu pengganti menggunakan opsi setOverrideDeadline().
  • Jika SeekBar memiliki nilai 0, pengguna belum menentukan batas waktu pengganti atau tugas periodik, jadi jangan tambahkan apa pun ke objek JobInfo.Builder.
  • Ganti kode yang menyetel batas waktu pengganti ke JobInfo.Builder dalam scheduleJob() dengan kode berikut untuk mengimplementasikan logika ini:
    if (mPeriodicSwitch.isChecked()){
       if (seekBarSet){
           builder.setPeriodic(seekBarInteger * 1000);
       } else {
           Toast.makeText(MainActivity.this,
               "Please set a periodic interval", Toast.LENGTH_SHORT).show();
       }
    } else {
       if (seekBarSet){
           builder.setOverrideDeadline(seekBarInteger * 1000);
       }
    }
    

Kode solusi

Projek Android Studio: NotificationScheduler

Tantangan penyusunan kode

Catatan:Semua tantangan penyusunan kode opsional dan bukan prasyarat untuk pelajaran berikutnya.

Tantangan: Sampai saat ini, tugas Anda dijadwalkan oleh JobService yang difokuskan pada pengiriman notifikasi. Namun, pada sebagian besar waktu, JobScheduler digunakan untuk tugas latar belakang yang lebih sulit, seperti memperbarui cuaca atau menyinkronkan dengan database. Karena tugas latar belakang sifatnya bisa lebih kompleks, baik dari sudut pandang program dan fungsionalitas, pekerjaan memberi tahu framework saat tugas selesai adalah tugas developer. Untungnya, developer bisa melakukannya dengan memanggil jobFinished().

  1. Implementasikan JobService yang memulai AsyncTask saat batasan yang diberikan terpenuhi. AsyncTask seharusnya tertidur selama 5 detik. Ini akan mewajibkan Anda untuk memanggil jobFinished() saat tugas selesai. Jika batasan tidak lagi terpenuhi saat thread tertidur, tampilkan pesan Toast yang mengatakan bahwa pekerjaan gagal dan jadwalkan ulang pekerjaan.

Rangkuman

  • JobScheduler menyediakan framework fleksibel untuk dengan cerdas menyelesaikan layanan latar belakang.
  • JobScheduler hanya tersedia pada perangkat yang menjalankan API 21+
  • Untuk menggunakan JobScheduler, Anda memerlukan dua bagian: JobService dan JobInfo.
  • JobInfo adalah serangkaian kondisi yang akan memicu pekerjaan berjalan.
  • JobService mengimplementasikan pekerjaan agar berjalan di bawah kondisi yang ditentukan oleh JobInfo.
  • Anda hanya perlu mengimplementasikan metode callback onStartJob() dan onStopJob() dalam JobService.
  • Implementasi pekerjaan terjadi (atau dimulai) di onStartJob().
  • onStartJob() mengembalikan boolean yang menandakan apakah layanan perlu memproses pekerjaan dalam thread yang berbeda.
  • Jika onStartJob() mengembalikan true, Anda harus secara eksplisit memanggil jobFinished(). Jika onStartJob() mengembalikan salah, waktu proses akan memanggil jobFinished() mewakili Anda.
  • JobService diproses pada thread utama, jadi hindari penghitungan panjang untuk I/O.
  • JobScheduler adalah kelas pengelola yang bertanggung jawab untuk menjadwalkan tugas batch task.JobScheduler bersama-sama untuk memaksimalkan efisiensi sumber daya sistem, yang berarti Anda tidak memiliki kontrol pasti tentang kapan tugas dieksekusi.

Konsep terkait

Dokumentasi konsep terkait ada di Dasar-Dasar Developer Android: Konsep.

Ketahui selengkapnya

Dokumentasi Developer Android

Referensi

results matching ""

    No results matching ""