Minggu, September 30, 2018

Dasar Android : Layanan

Layanan

Materi:
Dalam bab ini, Anda akan mempelajari tentang berbagai tipe layanan, cara menggunakannya, dan cara mengelola daur hidup layanan dalam aplikasi.

Apa yang dimaksud dengan layanan?

Layanan adalah komponen aplikasi yang menjalankan operasi yang berjalan lama, biasanya di latar belakang. Layanan tidak menyediakan antarmuka pengguna (UI). (Aktivitas, di sisi lain, menyediakan UI.)
Layanan bisa dimulaidiikat, atau keduanya:
  • Layanan yang dimulai adalah layanan yang komponen aplikasinya memulai dengan memanggil startService().
    Gunakan layanan yang dimulai untuk tugas yang berjalan di latar belakang guna menjalankan operasi yang berjalan lama. Selain itu, gunakan layanan yang dimulai untuk tugas yang menjalankan pekerjaan untuk proses jarak jauh.
  • Layanan terikat adalah layanan yang komponen aplikasinya diikat ke dirinya sendiri dengan memanggil bindService().
    Gunakan layanan terikat untuk tugas yang berinteraksi dengan komponen aplikasi lain guna menjalankan komunikasi interproses (IPC). Misalnya, layanan terikat mungkin menangani transaksi jaringan, menjalankan I/O file, memutar musik, atau berinteraksi dengan penyedia materi.
Catatan: Layanan berjalan di thread utama dari proses hosting-nya—layanan tidak membuat thread sendiri dan tidak berjalan di proses terpisah kecuali jika Anda menetapkannya.

Jika layanan Anda akan melakukan pekerjaan yang banyak membutuhkan CPU atau operasi pemblokiran (seperti pemutaran MP3 atau jaringan), buat thread baru dalam layanan untuk melakukan pekerjaan itu. Dengan menggunakan thread terpisah, Anda akan mengurangi risiko kesalahan Aplikasi Tidak Merespons (Application Not Responding/ANR) dan thread utama aplikasi bisa terus disediakan untuk interaksi pengguna dengan aktivitas Anda.
Untuk mengimplementasikan suatu jenis layanan dalam aplikasi Anda:
  1. Deklarasikan layanan di manifes.
  2. Buat kode implementasi, seperti yang dijelaskan dalam Layanan yang dimulai dan Layanan terikat, di bawah ini.
  3. Kelola daur hidup layanan.

Mendeklarasikan layanan di manifes

Sebagaimana dengan aktivitas dan komponen lainnya, Anda harus mendeklarasikan semua layanan dalam file manifes aplikasi. Untuk mendeklarasikan layanan, tambahkan elemen  sebagai anak dari elemen  . Misalnya:
...
android:exported="false" />
...
Untuk memblokir akses ke layanan dari aplikasi lainnya, deklarasikan layanan sebagai privat. Caranya, setel atribut android:exported ke false. Ini akan menghentikan aplikasi lain dari memulai layanan Anda, bahkan bila menggunakan maksud eksplisit.

Layanan yang dimulai

Cara memulai layanan:
  1. Komponen aplikasi seperti aktivitas memanggil startService() dan meneruskannya di Intent. Dalam hal ini Intent menetapkan layanan dan menyertakan data yang akan digunakan oleh layanan.
  2. Sistem akan memanggil metode onCreate() layanan dan callback lainnya yang sesuai di thread utama. Tergantung layanan untuk mengimplementasikan callback tersebut dengan perilaku yang sesuai, seperti membuat thread sekunder yang akan digunakan.
  3. Sistem akan memanggil metode onStartCommand() layanan, dengan meneruskan Intent yang disediakan oleh klien di langkah 1. (Klien dalam konteks ini adalah komponen aplikasi yang memanggil layanan.)
Setelah dimulai, layanan bisa berjalan di latar belakang tanpa dibatasi waktu, bahkan jika komponen yang memulainya telah dimusnahkan. Biasanya, layanan yang dimulai menjalankan operasi tunggal dan tidak mengembalikan hasil ke pemanggil. Misalnya, layanan dapat mengunduh atau mengunggah file melalui jaringan. Bila operasi selesai, layanan harus berhenti sendiri dengan memanggil stopSelf(), atau komponen lain bisa menghentikannya dengan memanggil stopService().
Misalnya, anggaplah aktivitas perlu menyimpan data ke database online. Aktivitas akan memulai layanan pendamping dengan meneruskan Intent ke startService(). Layanan menerima maksud di onStartCommand(), menghubungkan ke Internet, dan menjalankan transaksi database. Bila transaksi selesai, layanan akan menggunakan stopSelf() untuk menghentikan dirinya sendiri dan dimusnahkan. (Ini adalah contoh layanan yang ingin Anda jalankan di thread pekerja, sebagai ganti thread utama.)

IntentService

Sebagian besar layanan yang dimulai tidak perlu menangani beberapa permintaan secara bersamaan, dan jika layanan melakukannya, maka akan mengakibatkan skenario multi-threading yang berbahaya. Karena itu, sebaiknya Anda mengimplementasikan layanan menggunakan kelas IntentService .
IntentService adalah subkelas yang berguna dari Service:
  • IntentService secara otomatis menyediakan thread pekerja untuk menangani Intent.
  • IntentService menangani beberapa kode boilerplate yang diperlukan layanan umum (seperti memulai dan menghentikan layanan).
  • IntentService bisa membuat antrean pekerjaan yang meneruskan satu maksud untuk setiap kalinya ke implementasi onHandleIntent() , sehingga Anda tidak perlu mengkhawatirkan multi-threading.
Untuk mengimplementasikan IntentService:
  1. Sediakan konstruktor kecil untuk layanan.
  2. Buat implementasi onHandleIntent() untuk melakukan pekerjaan yang disediakan klien.
Inilah contoh implementasi IntentService:
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread. */
* The IntentService calls this method from the default worker thread with
public HelloIntentService() { super("HelloIntentService"); } /**
* stops the service, as appropriate.
* the intent that started the service. When this method returns, IntentService */ @Override protected void onHandleIntent(Intent intent) {
Thread.sleep(5000);
// Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { } catch (InterruptedException e) { // Restore interrupt status.
}
Thread.currentThread().interrupt(); }
}

Layanan terikat

Layanan "terikat" bila komponen aplikasi mengikatnya dengan memanggil bindService(). Layanan terikat menawarkan antarmuka klien-server yang memungkinkan komponen berinteraksi dengan layanan, mengirim permintaan, dan mendapatkan hasil, kadang-kadang menggunakan komunikasi interproses (IPC) untuk mengirim dan menerima informasi di seluruh proses. Layanan terikat hanya berjalan selama komponen aplikasi terikat padanya. Beberapa komponen bisa diikat ke layanan sekaligus, namun bila semuanya telah dilepas, layanan akan dimusnahkan.
Layanan terikat umumnya tidak mengizinkan memulai komponen dengan memanggil startService().

Mengimplementasikan layanan terikat

Untuk mengimplementasikan layanan terikat, definisikan antarmuka yang menetapkan cara klien bisa berkomunikasi dengan layanan. Antarmuka ini, yang dikembalikan layanan Anda dari metode callback onBind() , harus berupa implementasi IBinder.
Untuk mengambil antarmuka IBinder , komponen aplikasi klien memanggil bindService(). Setelah klien menerima IBinder, klien berinteraksi dengan layanan melalui antarmuka itu.
Ada sejumlah cara untuk mengimplementasikan layanan terikat, dan implementasi tersebut lebih rumit daripada layanan yang dimulai. Untuk detail selengkapnya tentang layanan terikat, lihat Layanan Terikat.

Mengikat ke layanan

Untuk mengikat ke layanan yang dideklarasikan di manifes dan diimplementasikan oleh komponen aplikasi, gunakan bindService() dengan Intenteksplisit.
Perhatian: Jangan gunakan maksud implisit untuk mengikat ke layanan. Melakukannya adalah bahaya keamanan, karena Anda tidak bisa memastikan layanan yang akan merespons maksud tersebut, dan pengguna tidak bisa melihat layanan mana yang dimulai. Mulai dengan Android 5.0 (API level 21), sistem membuat pengecualian jika Anda memanggil bindService() dengan Intentimplisit.

Daur hidup layanan

Daur hidup layanan lebih sederhana daripada aktivitas. Akan tetapi, ini jauh lebih penting karena Anda memerhatikan dari dekat cara layanan dibuat dan dimusnahkan. Karena tidak memiliki UI, layanan bisa terus berjalan di latar belakang tanpa diketahui pengguna, bahkan jika pengguna beralih ke aplikasi lain. Ini menghabiskan sumber daya dan menguras baterai.
Seperti aktivitas, layanan memiliki metode callback daur hidup yang bisa Anda implementasikan untuk memantau perubahan keadaan layanan dan melakukan pekerjaan pada waktu yang sesuai. Layanan kerangka berikut memperagakan setiap metode daur hidup:
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
@Override
boolean mAllowRebind; // indicates whether onRebind should be used public void onCreate() {
// The service is starting, due to a call to startService()
// The service is being created } @Override public int onStartCommand(Intent intent, int flags, int startId) {
// A client is binding to the service with bindService()
return mStartMode; } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override
public void onRebind(Intent intent) {
public boolean onUnbind(Intent intent) { // All clients have unbound with unbindService() return mAllowRebind; } @Override
// The service is no longer used and is being destroyed
// A client is binding to the service with bindService(), // after onUnbind() has already been called } @Override public void onDestroy() { }
}

Daur hidup layanan yang dimulai vs. layanan terikat

Layanan terikat hanya tersedia untuk menyajikan komponen aplikasi yang terikat padanya, sehingga bila tidak ada lagi komponen yang diikat ke layanan tersebut, sistem akan memusnahkannya. Layanan terikat tidak perlu dihentikan secara eksplisit seperti halnya layanan yang dimulai (menggunakan stopService()atau stopSelf()).
Diagram di bawah ini menampilkan perbandingan antara daur hidup layanan yang dimulai dan terikat.
Daur Hidup Layanan yang Dimulai dan Terikat

Layanan latar depan

Walaupun sebagian besar layanan berjalan di latar belakang, sebagian lagi ada yang berjalan di latar depan. Layanan latar depan adalah layanan yang diketahui pengguna, jadi ini bukan layanan yang bakal dimatikan sistem bila memori tinggal sedikit.
Misalnya, pemutar musik yang memutar musik dari layanan harus disetel untuk berjalan di latar depan, karena pengguna mengetahui operasinya. Notifikasi di bilah status dapat menunjukkan lagu saat ini dan memungkinkan pengguna meluncurkan aktivitas untuk berinteraksi dengan pemutar musik.
Untuk meminta agar layanan berjalan di latar depan, panggil startForeground() sebagai ganti startService(). Metode ini menggunakan dua parameter: integer yang secara unik mengidentifikasi notifikasi dan Notification untuk bilah status. Notifikasi ini sedang berlangsung, artinya tidak bisa ditutup. Notifikasi tetap berada di bilah status hingga layanan dihentikan atau dibuang dari latar depan.
Misalnya:
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
startForeground(ONGOING_NOTIFICATION_ID, mBuilder.build());
.setContentText("Hello World!");
Catatan: ID integer yang Anda berikan ke startForeground() tidak boleh 0.
Untuk membuang layanan dari latar depan, panggil stopForeground(). Metode ini memerlukan boolean, yang menunjukkan apakah akan membuang notifikasi bilah status atau tidak. Metode ini tidak menghentikan layanan. Akan tetapi, jika Anda menghentikan layanan sewaktu masih berjalan di latar depan, maka notifikasi juga akan dibuang.

Layanan terjadwal

Untuk API level 21 dan yang lebih tinggi, Anda bisa meluncurkan layanan menggunakan JobSchedulerAPI. Untuk menggunakan JobScheduler, Anda perlu mendaftarkan tugas dan menetapkan persyaratannya untuk jaringan dan pengaturan waktu. Sistem menjadwalkan tugas untuk dieksekusi di waktu yang tepat.