8.2: Alarm Manager
Daftar Isi:
- Yang harus sudah Anda KETAHUI
- Yang akan Anda PELAJARI
- Yang akan Anda LAKUKAN
- Tugas 1. Menyiapkan Proyek dan Tampilan Parking Alarm
- Tugas 2. Menyiapkan Notifikasi
- Tugas 3. Membuat Alarm Berulang
- Tantangan penyusunan kode
- Rangkuman
- Konsep terkait
Dalam praktik sebelumnya, Anda telah mempelajari cara membuat aplikasi merespons interaksi pengguna dengan menekan tombol atau mengetuk notifikasi. Anda juga belajar cara membuat aplikasi merespons peristiwa sistem menggunakan BroadcastReceivers. Namun bagaimana jika aplikasi perlu mengambil tindakan pada waktu yang spesifik, seperti pada kasus notifikasi kalender? Dalam kasus ini, Anda perlu menggunakan AlarmManager, kelas yang mengizinkan Anda meluncurkan dan mengulangi PendingIntent pada waktu dan interval yang spesifik.
Dalam praktik ini Anda akan membuat timer yang akan mengingatkan Anda untuk berdiri jika sudah duduk terlalu lama.
Yang harus sudah Anda KETAHUI
Dari praktik sebelumnya, Anda harus sudah bisa:
- Mengimplementasikan listener onCheckChanged untuk tombol toggle.
- Menyiapkan intent siaran khusus.
- Menggunakan penerima siaran.
- Mengirimkan notifikasi.
Yang akan Anda PELAJARI
Anda akan belajar:
- Menjadwalkan alarm berulang dengan AlarmManager.
- Memeriksa apakah Alarm sudah disiapkan.
- Membatalkan alarm berulang.
Yang akan Anda LAKUKAN
Dalam praktik ini Anda akan:
- Menyetel alarm berulang untuk memberi tahu Anda setiap lima belas menit.
- Menggunakan ToggleButton untuk menyetel dan melacak alarm.
- Menggunakan pesan Toast untuk memberitahukan pengguna saat Alarm diaktifkan atau dinonaktifkan.
Ringkasan Aplikasi
Stand Up! adalah aplikasi yang membantu Anda tetap sehat dengan mengingatkan Anda untuk berdiri dan berjalan-jalan setiap sekitar lima belas menit. Aplikasi ini menggunakan notifikasi untuk memberi tahu Anda ketika lima belas menit sudah berlalu. Aplikasi menyertakan tombol alih yang dapat mengaktifkan dan menonaktifkan alarm.
Tugas 1. Menyiapkan Stand Up! Proyek dan Tampilan
1.1 Membuat Stand Up! Layout proyek
- Membuat proyek baru bernama "Stand Up!, menerima opsi default dan menggunakan template aktivitas kosong.
- Hapus TextView default dan tambahkan elemen berikut:
TextView
Atribut
Nilai
android:layout_width
"wrap_content"
android:layout_height
"wrap_content"
android:layout_above
"@+id/alarmToggle"
android:layout_centerHorizontal
"true"
android:layout_margin
"8dp"
android:text
"Stand Up Alarm"
android:textAppearance
@style/TextAppearance.AppCompat.Headline
ToggleButton
Atribut
Nilai
android:id
"@+id/alarmToggle"
android:layout_width
"wrap_content"
android:layout_height
"wrap_content"
android:layout_centerHorizontal
"true"
android:layout_centerVertical
"true"
1.2 Menyiapkan metode setOnCheckedChangeListener()
Aplikasi Stand Up! memiliki tombol alih yang digunakan untuk menyetel dan membatalkan alarm, sekaligus tampak mewakili status alarm saat ini. Untuk menyetel alarm saat tombol alih diaktifkan, Anda perlu menggunakan metode onCheckedChangeListener()
:
- Dalam metode MainActivity
onCreate()
, temukan Alarm Toggle menurut id. Panggil
setOnCheckedChangeListener()
pada instance tombol alih, dan mulai mengetik "new OnCheckedChangeListener
". Android Studio akan menyelesaikan metode untuk Anda secara otomatis, termasuk metode penggantianonCheckedChanged()
yang diperlukan. Metode ini memiliki dua parameter: CompoundButton yang diklik (dalam kasus ini tombol Toggle Alarm), dan boolean yang mewakili status Tombol Toggle saat ini (yakni, apakah tombol alih saat ini diaktifkan atau dinonaktifkan).alarmToggle.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) { } });
Akan sangat berguna jika pengguna menerima masukan selain tombol alih yang diaktifkan dan dinonaktifkan untuk menujukkan bahwa alarm memang disetel (Anda belum mengimplementasikan alarm, ini akan dilakukan pada bagian berikutnya). Setel blok if/else menggunakan parameter boolean dalam metode
onCheckedChanged()
yang mengirimkan pesan toast untuk memberi tahu pengguna apakah alarm diaktifkan atau dinonaktifkan. Jangan lupa untuk mengekstrak sumber daya string.String toastMessage; if(isChecked){ //Set the toast message for the "on" case toastMessage = getString(R.string.alarm_on_toast); } else { //Set the toast message for the "off" case toastMessage = getString(R.string.alarm_off_toast); } //Show a toast to say the alarm is turned on or off Toast.makeText(MainActivity.this, toastMessage, Toast.LENGTH_SHORT) .show();
Tugas 2. Menyiapkan Notifikasi
Langkah berikutnya adalah membuat notifikasi yang akan mengingatkan pengguna untuk berdiri setiap lima belas menit. Untuk sekarang, notifikasi akan dikirimkan segera setelah tombol alih disetel.
2.1 Membuat notifikasi
Pada langkah ini Anda akan membuat metode deliverNotification()
yang akan mengeposkan pengingat untuk berdiri dan berjalan-jalan.
- Buat variabel anggota dalam MainActivity bernama mNotificationManager dari tipe NotificationManager.
- Inisialisasikan dalam
onCreate()
dengan memanggilgetSystemService()
:mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- Buat metode MainActivity bernama
deliverNotification()
yang mengambil Context sebagai argumen dan tidak mengembalikan apa pun.private void deliverNotification(Context context) {}
- Buat konstanta anggota dalam MainActivity bernama NOTIFICATION_ID dan setel ke 0. Aplikasi hanya akan mendapatkan satu notifikasi pada satu waktu, jadi Anda akan menggunakan id notifikasi yang sama untuk semua notifikasi.Catatan: ID Notifikasi digunakan untuk membedakan notifikasi dalam aplikasi. Pengelola Notifikasi hanya bisa membatalkan notifikasi yang dikirimkan dari aplikasi agar Anda bisa menggunakan ID yang sama dalam aplikasi yang berbeda.
Intent Konten Notifikasi
- Buat Intent dalam
onCreate()
yang akan Anda gunakan untuk Intent Konten notifikasi:Intent contentIntent = new Intent(context, MainActivity.class);
- Buat PendingIntent dari Intent konten tepat di bawah definisi contentIntent menggunakan metode
getActivity()
, meneruskan ID notifikasi dan menggunakanFLAG_UPDATE_CURRENT flag:
PendingIntent contentPendingIntent = PendingIntent.getActivity (context, NOTIFICATION_ID, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Catatan: bendera PendingIntent memberi tahu sistem cara menangani situasi saat banyak instance PendingIntent yang sama dibuat (maksudnya berisi intent yang sama). Bendera FLAG_UPDATE_CURRENT memerintahkan sistem untuk menggunakan Intent lama tetapi mengganti data ekstra. Karena Anda tidak memiliki ekstra dalam intent ini, Anda akan menggunakan kembali PendingIntent yang sama berulang-ulang.
Judul dan Teks Notifikasi
- Buat sumber daya string dalam file strings.xml bernama notification_title. Setel agar setara dengan "Stand Up Alert".
- Buat sumber daya string dalam file strings.xml bernama notification_text. Setel agar setara dengan "You should stand up and walk around now!".
Ikon Notifikasi
- Tambahkan aset gambar untuk digunakan sebagai ikon notifikasi (gunakan Image Asset Studio). Pilih ikon apa pun yang Anda rasa cocok untuk alarm ini:
Buat notifikasi
- Gunakan NotificationCompat.Builder untuk membuat notifikasi dalam metode
deliverNotification()
menggunakan judul, teks, ikon, dan intent konten notifikasi di atas.NotificationCompat.Builder builder = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_stand_up) .setContentTitle(context.getString(R.string.notification_title)) .setContentText(context.getString(R.string.notification_text)) .setContentIntent(contentPendingIntent)
- Setel prioritas Notifikasi ke PRIORITY_HIGH:
.setPriority(NotificationCompat.PRIORITY_HIGH)
- Tambahkan opsi ke builder untuk menyetel AutoCancel ke true, dan opsi lainnya untuk menggunakan lampu, suara dan pola getar default:
.setAutoCancel(true) .setDefaults(NotificationCompat.DEFAULT_ALL);
Kirim notifikasi
- Gunakan NotificationManager untuk mengirimkan notifikasi:
mNotificationManager.notify(NOTIFICATION_ID, builder.build());
- Panggil
deliverNotification()
saat tombol alih alarm diaktifkan, meneruskan konteks aktivitas: Panggil
cancelAll()
pada NotificationManager jika tombol alih dinonaktifkan untuk menghapus notifikasi.if(isChecked){ deliverNotification(MainActivity.this); //Set the toast message for the "on" case toastMessage = getString(R.string.alarm_on_toast); } else { //Cancel notification if the alarm is turned off mNotificationManager.cancelAll(); //Set the toast message for the "off" case toastMessage = getString(R.string.alarm_off_toast); }
- Jalankan aplikasi dan periksa apakah notifikasi dikirimkan dengan semua opsi yang diinginkan.
Pada tahap ini tidak ada alarm sama sekali: notifikasi segera dikirimkan saat tombol alih alarm diaktifkan. Dalam bagian ini, Anda akan mengimplementasikan AlarmManager untuk menjadwalkan dan mengirimkan notifikasi setiap 15 menit sekali.
Tugas 3. Membuat Alarm Berulang
Sekarang karena aplikasi sudah dapat mengirimkan notifikasi, waktunya untuk mengimplementasikan komponen utama aplikasi: AlarmManager. Ini adalah kelas yang akan bertanggung jawab untuk mengirimkan pegingat secara berkala agar Anda berdiri. AlarmManager memiliki banyak jenis alarm bawaan, baik alarm satu waktu maupun alarm periodik, alarm eksak atau tidak eksak. Untuk mengetahui selengkapnya tentang jenis-jenis alarm, lihat panduan ini.
AlarmManager, seperti notifikasi, menggunakan PendingIntent sehingga dikirim dengan opsi yang spesifik. Karena hal ini, AlarmManager dapat mengirimkan Intent saat aplikasi tidak berjalan lagi. Dalam aplikasi ini, PendingIntent akan mengirimkan siaran Intent dengan tindakan "Notify".
Intent siaran akan diterima oleh penerima siaran yang mengambil tindakan yang tepat (mengirimkan notifikasi).
AlarmManager dapat memicu peristiwa sekali waktu atau berulang yang terjadi saat perangkat tertidur atau aplikasi tidak berjalan. Peristiwa dapat dijadwalkan dengan pilihan currentTimeMillis() saat menggunakan versi real time (RTC) atau elapsedRealtime() saat menggunakan versi waktu yang sudah berlalu (ELAPSED_REALTIME), dan mengirimkan PendingIntent saat terjadi. Untuk informasi selengkapnya tentang jam berbeda yang tersedia dan informasi tentang cara mengontrol waktu peristiwa, lihat Referensi Developer SystemClock.
3.1 Menyiapkan intent tertunda siaran
AlarmManager bertanggung jawab untuk mengirimkan PendingIntent pada interval waktu yang telah ditentukan. PendingIntent ini akan mengirimkan intent siaran yang memberi tahu aplikasi kapan waktunya untuk memperbarui waktu yang tersisa dalam notifikasi.
Buat konstanta string sebagai variabel anggota dalam MainActivity untuk digunakan sebagai tindakan intent siaran yang akan mengirimkan notifikasi:
private static final String ACTION_NOTIFY = "com.example.android.standup.ACTION_NOTIFY";
Catatan: gunakan nama paket yang berkualitas untuk string Intent, untuk memastikan Siaran unik, dan tidak dapat digunakan secara tidak sengaja oleh aplikasi lain dengan tindakan yang serupa.Buat Intent bernama notifyIntent dalam
onCreate()
dengan string khusus sebagai tindakannya:Intent notifyIntent = new Intent(ACTION_NOTIFY);
- Buat PendingIntent notifikasi menggunakan konteks, variabel NOTIFICATION_ID, intent notifikasi baru, dan bendera PendingIntent UPDATE_CURRENT:
PendingIntent notifyPendingIntent = PendingIntent.getBroadcast (this, NOTIFICATION_ID, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
3.2 Menyetel alarm berulang
Anda sekarang akan menggunakan AlarmManager untuk mengirimkan Intent siaran setiap 15 menit. Untuk tugas ini, jenis alarm yang tepat adalah alarm tidak eksak berulang yang menggunakan waktu yang sudah lewat dan akan mengaktifkan perangkat jika tertidur. Jam real time tidak relevan di sini, karena kita ingin mengirimkan notifikasi setiap lima belas menit.
- Inisialisasi AlarmManager dalam
onCreate()
dengan memanggilgetSystemService()
:AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
- Dalam metode
onCheckedChanged()
, panggilsetInexactRepeating()
pada instance alarm manager saat pengguna mengeklik "ON" pada Alarm (Parameter keduanya adalahtrue
). Anda akan menggunakan alarmsetInexactRepeating()
karena lebih efisien sumber daya untuk menggunakan penentuan waktu yang tidak tepat (sistem dapat membundel alarm dari beberapa aplikasi yang berbeda) dan alarm tidak perlu pas berulang setiap 15 menit. MetodesetInexactRepeating()
mengambil 4 argumen: - Jenis alarm. Pada kasus ini Anda menggunakan tipe waktu yang sudah lewat sejak boot, karena hanya waktu relatif yang penting. Anda juga akan mengaktifkan perangkat jika tertidur, sehingga jenis alarmnya adalah ELAPSED_REALTIME_WAKEUP.
- Waktu pemicu dalam milidetik. Untuk ini, gunakan waktu yang sudah lewat, plus 15 menit. Untuk mendapatkan waktu yang sudah lewat, Anda bisa memanggil SystemClock.elapsedRealtime(). Lalu Anda bisa menggunakan konstanta AlarmManager untuk menambahkan 15 menit ke waktu yang sudah lewat:
AlarmManager.INTERVAL_FIFTEEN_MINUTES
. - Interval waktu dalam milidetik. Anda ingin agar notifikasi diposting setiap 15 menit. Anda bisa menggunakan konstanta AlarmManager.INTERVAL_FIFTEEN_MINUTES lagi.
PendingIntent yang akan dikirim. Anda membuat PendingIntent pada tugas sebelumnya.
long triggerTime = SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_FIFTEEN_MINUTES; long repeatInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES; //If the Toggle is turned on, set the repeating alarm with a 15 minute interval alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, repeatInterval, notifyPendingIntent);
Catatan: Karena Anda mengakses instance AlarmManager dan notifyPendingIntent dari kelas bagian dalam yang anonim, Android Studio dapat menjadikan instance ini final. Jika tidak, Anda harus menjadikannya final sendiri.Hapus panggilan ke
deliverNotification()
dalam metodeonCheckedChanged()
.- Jika tombol alih alarm dinonaktifkan (dengan mengeklik toggle dalam status ON), batalkan alarm dengan memanggil
cancel()
pada AlarmManager, yang meneruskan intent tertunda yang digunakan untuk membuat alarm.
Pertahankan panggilan ke cancelAll() di NotificationManager, karena menonaktifkan tombol alih seharusnya tetap menghapus notifikasi yang ada.alarmManager.cancel(notifyPendingIntent);
AlarmManager sekarang akan mulai mengirimkan Intent Siaran mulai dari lima belas menit sejak Alarm disetel, dan setiap lima belas menit setelahnya. Aplikasi harus bisa merespons intent ini dengan mengirimkan notifikasi. Pada langkah selanjutnya Anda akan membuat subkelas Penerima Siaran untuk menerima intent siaran dan mengirimkan notifikasi.
3.3 Membuat Penerima Siaran
Penerima Siaran bertanggung jawab untuk menerima intent siaran dari AlarmManager dan bereaksi dengan tepat.
- Dalam Android Studio, klik File > New > Other > Broadcast Receiver.
- Masukkan AlarmReceiver sebagai namanya, pastikan kotak centang Exported sudah tidak dicentang (untuk memastikan aplikasi lain tidak dapat memanggil Penerima Siaran ini). Anda juga bisa mengubah setelan ini dalam AndroidManifest dengan menyetel atribut
android:exported
kefalse
. Android Studio akan membuat subkelas BroadcastReceiver dengan metode yang diperlukan (onReceive()
), dan menambahkan penerima ke AndroidManifest. Anda mungkin perlu menambahkan Filter Intent ke tag<receiver>
dalam AndroidManifest untuk memilih Intent Siaran masuk yang tepat. - Dalam Manifes Android, buat
<intent-filter>
tag pembuka dan penutup di antara tag<receiver>
buat sebuah item<action>
dalam filter maksud denganandroid:name
disetel ke string tindakan ACTION_NOTIFY khusus yang Anda buat:<intent-filter> <action android:name="com.example.android.standup.ACTION_NOTIFY" /> </intent-filter>
- Salin dan tempel metode
deliverNotification()
ke metodeonReceive()
dalam BroadcastReceiver dan panggil darionReceive()
. Pengelola notifikasi dan id notifikasi belum diinisialisasi dalam kelas BroadcastReceiver jadi akan disorot dengan warna merah. - Salin variabel NOTIFICATION_ID dari MainActivity ke dalam kelas BroadcastReceiver.
- Inisialisasi NotificationManager di awal metode
onReceive()
. Anda harus memanggil getSystemService() dari yang diteruskan dalam Konteks:NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- Hapus baris yang memunculkan UnsupportedOperationException.
- Jalankan aplikasi Anda. Jika tidak ingin menunggu lima belas menit untuk melihat notifikasi, Anda bisa mengubah waktu pemicu ke
SystemClock.elapsedRealtime()
untuk segera melihat notifikasi. Anda juga bisa mengubah interval ke waktu yang lebih singkat untuk memastikan bahwa alarm berulang berfungsi.
Sekarang Anda memiliki aplikasi yang dapat menjadwalkan dan melakukan operasi berulang, bahkan jika aplikasi tidak lagi berjalan. Lanjutkan, keluar dari aplikasi, notifikasi akan tetap dikirimkan. Ada satu komponen terakhir yang akan memastikan pengalaman pengguna yang layak: jika aplikasi ditutup, tombol alih akan disetel ulang ke status nonaktif, bahkan jika alarm sudah disetel. Untuk memperbaikinya, Anda perlu memeriksa status alarm setiap kali aplikasi diluncurkan.
3.5 Memeriksa Status Alarm
Untuk melacak status alarm, Anda memerlukan variabel boolean yang true
jika alarm sudah ada, dan false
jika belum. Untuk menyetel boolean ini, Anda bisa memanggil PendingIntent.getBroadcast()
dengan bendera PendingIntent FLAG_NO_CREATE. Dalam hal ini, PendingIntent dikembalikan jika sudah ada, atau kelas mengembalikan null. Memeriksa apakah alarm sudah disetel sangatlah berguna.
- Buat boolean yang benar jika PendingIntent tidak null, dan sebaliknya salah, menggunakan strategi ini. Gunakan boolean untuk menyetel status ToggleButton dengan benar saat aplikasi dimulai. Kode ini harus datang sebelum PendingIntent dibuat, atau kode akan selalu mengembalikan benar:
boolean alarmUp = (PendingIntent.getBroadcast(this, NOTIFICATION_ID, notifyIntent, PendingIntent.FLAG_NO_CREATE) != null);
- Setel keadaan tombol alih segera setelah Anda mendefinisikan boolean alarmUp:
Ini akan memastikan tombol alih selalu diaktifkan jika alarm disetel, dan dinonaktifkan jika tidak. Itu saja. Sekarang Anda memiliki alarm terjadwal yang akan mengingatkan Anda untuk berdiri setiap lima belas menit.alarmToggle.setChecked(alarmUp);
- Jalankan aplikasi Anda. Aktifkan alarm. Keluar dari aplikasi. Buka aplikasi lagi. Tombol alarm akan menunjukkan bahwa alarm aktif.
Kode solusi
**Proyek Android Studio: StandUp
Tantangan penyusunan kode
Kelas AlarmManager juga menangani jam alarm untuk fungsi yang biasa, misalnya yang membangunkan Anda di pagi hari. Pada perangkat yang menjalankan API 21+, Anda bisa mendapatkan informasi tentang jam alarm jenis ini berikutnya dengan memanggil getNextAlarmClock()
pada pengelola alarm.
Tambahkan tombol ke aplikasi yang menampilkan waktu jam alarm berikutnya, yang telah disetel pengguna dalam pesan Toast.
Rangkuman
- AlarmManager mengizinkan Anda untuk menjadwalkan tugas berdasarkan jam real time atau waktu yang sudah lewat sejak booting.
- AlarmManager menyediakan berbagai jenis alarm, yang periodik dan sekali waktu, dengan opsi untuk mengaktifkan perangkat jika tertidur.
- AlarmManager ditujukan untuk situasi saat penentuan waktu yang tepat sangatlah penting (seperti acara kalender). Jika tidak, pertimbangkan framework Penjadwalan Pekerjaan untuk penentuan waktu dan penjadwalan yang lebih efisien sumber daya.
- Gunakan versi penentuan waktu yang tidak tepat dari AlarmManager kapan pun memungkinkan untuk meminimalkan beban yang disebabkan oleh banyaknya perangkat pengguna atau aplikasi yang melakukan tugas pada waktu yang bersamaan.
- AlarmManager menggunakan PendingIntent untuk melakukan operasi, jadi Anda bisa menjadwalkan siaran, layanan, dan aktivitas menggunakan PendingIntent yang tepat.
Konsep terkait
Dokumentasi konsep terkait ada di Dasar-Dasar Developer Android: Konsep.
Ketahui selengkapnya
Dokumentasi Developer Android
Panduan
Referensi