Menerima pembaruan lokasi di Android dengan Kotlin

1. Sebelum memulai

Android 10 dan 11 memberi pengguna kontrol lebih besar atas akses aplikasi ke lokasi perangkat mereka.

Saat aplikasi yang berjalan di Android 11 meminta akses lokasi, pengguna memiliki empat opsi:

  • Selalu izinkan
  • Izinkan hanya saat aplikasi digunakan (di Android 10)
  • Hanya satu kali (di Android 11)
  • Tolak

Android 10

6a1029175b467c77.png

Android 11

73d8cc88c5877c25.png

Dalam codelab ini, Anda akan mempelajari cara menerima update lokasi dan cara mendukung lokasi di semua versi Android, terutama Android 10 dan 11. Di akhir codelab, Anda akan memiliki aplikasi yang mengikuti praktik terbaik saat ini untuk mengambil update lokasi.

Prasyarat

Yang akan Anda lakukan

  • Ikuti praktik terbaik untuk lokasi di Android.
  • Menangani izin akses lokasi latar depan (saat pengguna meminta agar aplikasi Anda mengakses lokasi perangkat saat aplikasi Anda sedang digunakan).
  • Ubah aplikasi yang ada untuk menambahkan dukungan dalam meminta akses lokasi dengan menambahkan kode untuk berlangganan dan berhenti berlangganan ke lokasi.
  • Tambahkan dukungan ke aplikasi untuk Android 10 dan 11 dengan menambahkan logika untuk mengakses lokasi di lokasi latar depan atau saat digunakan.

Yang Anda butuhkan

  • Android Studio 3.4 atau yang lebih baru untuk menjalankan kode
  • Perangkat/emulator yang menjalankan pratinjau developer Android 10 dan 11

2. Memulai

Meng-clone repositori project awal

Untuk memulainya secepat mungkin, Anda dapat mengembangkan project awal ini. Jika sudah menginstal Git, Anda cukup menjalankan perintah berikut:

 git clone https://github.com/android/codelab-while-in-use-location

Jangan ragu untuk langsung membuka halaman GitHub.

Jika tidak memiliki Git, Anda bisa mendapatkan project sebagai file ZIP:

Mengimpor project

Buka Android Studio, pilih "Open an existing Android Studio project" dari layar selamat datang, lalu buka direktori project.

Setelah project dimuat, Anda juga akan melihat notifikasi bahwa Git tidak melacak semua perubahan lokal. Anda dapat mengklik Abaikan. (Anda tidak akan mendorong perubahan apa pun kembali ke repositori Git.)

Di sudut kiri atas jendela project, Anda akan melihat sesuatu seperti gambar di bawah jika berada dalam tampilan Android. (Jika berada dalam tampilan Project, Anda harus memperluas project untuk melihat hal yang sama.)

fa825dae96c5dc18.png

Ada dua folder (base dan complete). Masing-masing dikenal sebagai "modul".

Perlu diketahui bahwa Android Studio mungkin memerlukan waktu beberapa detik untuk mengompilasi project di latar belakang untuk pertama kalinya. Selama durasi ini, Anda akan melihat pesan berikut di status bar di bagian bawah Android Studio:

c2273e7835c0841a.png

Tunggu hingga Android Studio selesai mengindeks dan mem-build project sebelum membuat perubahan kode. Ini akan memungkinkan Android Studio menarik semua komponen yang diperlukan.

Jika Anda ditanya Reload for language changes to take effect? atau yang serupa, pilih Yes.

Memahami project awal

Anda sudah menyiapkan dan siap meminta lokasi di aplikasi. Gunakan modul base sebagai titik awal. Selama setiap langkah, tambahkan kode ke modul base. Setelah Anda menyelesaikan codelab ini, kode di modul base akan cocok dengan konten modul complete. Modul complete dapat digunakan untuk memeriksa pekerjaan Anda atau sebagai referensi jika Anda mengalami masalah apa pun.

Komponen utamanya meliputi:

  • MainActivity—UI bagi pengguna untuk mengizinkan aplikasi mengakses lokasi perangkat
  • LocationService—layanan yang berlangganan dan berhenti berlangganan perubahan lokasi, serta mempromosikan dirinya ke layanan latar depan (dengan notifikasi) jika pengguna keluar dari aktivitas aplikasi. Anda menambahkan kode lokasi di sini.
  • Util—Menambahkan fungsi ekstensi untuk class Location dan menyimpan lokasi di SharedPreferences (lapisan data yang disederhanakan).

Penyiapan emulator

Untuk mengetahui informasi tentang cara menyiapkan emulator Android, lihat Menjalankan di emulator.

Menjalankan project awal

Jalankan aplikasi Anda.

  1. Hubungkan perangkat Android ke komputer atau mulai emulator. (Pastikan perangkat menjalankan Android 10 atau yang lebih baru.)
  2. Di toolbar, pilih konfigurasi base dari pemilih drop-down, lalu klik Run:

99600e9d44527ab.png

  1. Perhatikan aplikasi berikut muncul di perangkat Anda:

99bf1dae46f99af3.png

Anda mungkin melihat bahwa tidak ada informasi lokasi yang muncul di layar output. Hal ini karena Anda belum menambahkan kode lokasi.

3. Menambahkan lokasi

Konsep

Fokus codelab ini adalah menunjukkan cara menerima update lokasi, dan akhirnya mendukung Android 10 dan Android 11.

Namun, sebelum Anda mulai membuat kode, sebaiknya tinjau dasar-dasarnya.

Jenis akses lokasi

Anda mungkin ingat empat opsi berbeda untuk akses lokasi dari awal codelab. Lihat apa maksudnya:

  • Izinkan hanya saat aplikasi digunakan
  • Opsi ini adalah opsi yang direkomendasikan untuk sebagian besar aplikasi. Dikenal juga sebagai akses "saat digunakan" atau "khusus latar depan", opsi ini ditambahkan di Android 10 dan memungkinkan developer mengambil lokasi hanya saat aplikasi sedang aktif digunakan. Aplikasi dianggap aktif jika salah satu dari pernyataan berikut benar:
  • Aktivitas dapat dilihat.
  • Layanan latar depan berjalan dengan notifikasi berkelanjutan.
  • Hanya sekali
  • Ditambahkan di Android 11, opsi ini sama dengan Izinkan hanya saat menggunakan aplikasi, tetapi untuk jangka waktu terbatas. Untuk mengetahui informasi selengkapnya, lihat Izin sekali beri.
  • Tolak
  • Opsi ini mencegah akses ke informasi lokasi.
  • Izinkan sepanjang waktu
  • Opsi ini memungkinkan akses lokasi sepanjang waktu, tetapi memerlukan izin tambahan untuk Android 10 dan yang lebih tinggi. Anda juga harus memastikan bahwa Anda memiliki kasus penggunaan yang valid dan mematuhi kebijakan lokasi. Anda tidak akan membahas opsi ini dalam codelab ini, karena opsi ini adalah kasus penggunaan yang lebih jarang. Namun, jika Anda memiliki kasus penggunaan yang valid dan ingin memahami cara menangani lokasi yang diakses setiap saat dengan benar, termasuk mengakses lokasi di latar belakang, tinjau contoh LocationUpdatesBackgroundKotlin.

Layanan, layanan latar depan, dan pengikatan

Untuk mendukung sepenuhnya update lokasi Izinkan hanya saat aplikasi digunakan, Anda harus memperhitungkan saat pengguna keluar dari aplikasi Anda. Jika ingin terus menerima update dalam situasi tersebut, Anda harus membuat layanan latar depan Service dan mengaitkannya dengan Notification.

Selain itu, jika Anda ingin menggunakan Service yang sama untuk meminta update lokasi saat aplikasi Anda terlihat dan saat pengguna keluar dari aplikasi Anda, Anda harus mengikat/melepas ikatan Service tersebut ke elemen UI.

Karena codelab ini hanya berfokus pada mendapatkan update lokasi, Anda dapat menemukan semua kode yang diperlukan di class ForegroundOnlyLocationService.kt. Anda dapat menjelajahi class tersebut dan MainActivity.kt untuk melihat cara kerjanya bersama-sama.

Untuk mengetahui informasi selengkapnya, lihat Ringkasan layanan dan Ringkasan layanan terikat.

Izin

Agar dapat menerima pembaruan lokasi dari NETWORK_PROVIDER atau GPS_PROVIDER, Anda harus meminta izin pengguna dengan mendeklarasikan izin ACCESS_COARSE_LOCATION atau ACCESS_FINE_LOCATION, dalam file manifes Android Anda. Tanpa izin ini, aplikasi Anda tidak akan dapat meminta akses ke lokasi saat runtime.

Izin tersebut mencakup kasus Khusus sekali ini dan Izinkan hanya saat aplikasi digunakan saat aplikasi Anda digunakan di perangkat yang menjalankan Android 10 atau yang lebih tinggi.

Lokasi

Aplikasi Anda dapat mengakses kumpulan layanan lokasi yang didukung melalui class di paket com.google.android.gms.location.

Lihat class utama:

  • FusedLocationProviderClient
  • Ini adalah komponen utama framework lokasi. Setelah dibuat, Anda menggunakannya untuk meminta pembaruan lokasi dan mendapatkan lokasi terakhir yang diketahui.
  • LocationRequest
  • Objek ini adalah objek data yang berisi parameter kualitas layanan untuk permintaan (interval untuk update, prioritas, dan akurasi). Nilai ini diteruskan ke FusedLocationProviderClient saat Anda meminta pembaruan lokasi.
  • LocationCallback
  • Setelan ini digunakan untuk menerima notifikasi saat lokasi perangkat telah berubah atau tidak dapat lagi ditentukan. Ini meneruskan LocationResult tempat Anda bisa mendapatkan Location untuk disimpan di database Anda.

Setelah memiliki gambaran dasar tentang apa yang Anda lakukan, mulailah dengan kode.

4. Menambahkan fitur lokasi

Codelab ini berfokus pada opsi lokasi yang paling umum: Izinkan hanya saat aplikasi digunakan.

Untuk menerima pembaruan lokasi, aplikasi Anda harus memiliki aktivitas yang terlihat atau layanan yang berjalan di latar depan (dengan notifikasi).

Izin

Tujuan codelab ini adalah untuk menunjukkan cara menerima pembaruan lokasi, bukan cara meminta izin akses lokasi, sehingga kode berbasis izin sudah ditulis untuk Anda. Anda bisa melewatinya jika sudah memahaminya.

Berikut adalah ringkasan izin (tidak ada tindakan yang diperlukan untuk bagian ini):

  1. Nyatakan izin yang Anda gunakan di AndroidManifest.xml.
  2. Sebelum mencoba mengakses informasi lokasi, periksa apakah pengguna telah memberikan izin kepada aplikasi Anda untuk melakukannya. Jika aplikasi Anda belum menerima izin, minta akses.
  3. Menangani pilihan izin pengguna. (Anda dapat melihat kode ini di MainActivity.kt.)

Jika Anda menelusuri TODO: Step 1.0, Review Permissions di AndroidManifest.xml atau MainActivity.kt, Anda akan melihat semua kode yang ditulis untuk izin.

Untuk mengetahui informasi selengkapnya, lihat Ringkasan izin.

Sekarang, mulai tulis beberapa kode lokasi.

Meninjau variabel utama yang diperlukan untuk pembaruan lokasi

Di modul base, telusuri TODO: Step 1.1, Review variables di

File ForegroundOnlyLocationService.kt.

Tidak ada tindakan yang diperlukan dalam langkah ini. Anda hanya perlu meninjau blok kode berikut, beserta komentarnya, untuk memahami class dan variabel utama yang Anda gunakan untuk menerima update lokasi.

// TODO: Step 1.1, Review variables (no changes).
// FusedLocationProviderClient - Main class for receiving location updates.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

// LocationRequest - Requirements for the location updates, i.e., how often you
// should receive updates, the priority, etc.
private lateinit var locationRequest: LocationRequest

// LocationCallback - Called when FusedLocationProviderClient has a new Location.
private lateinit var locationCallback: LocationCallback

// Used only for local storage of the last known location. Usually, this would be saved to your
// database, but because this is a simplified sample without a full database, we only need the
// last location to create a Notification if the user navigates away from the app.
private var currentLocation: Location? = null

Tinjau inisialisasi FusedLocationProviderClient

Di modul base, telusuri TODO: Step 1.2, Review the FusedLocationProviderClient dalam file ForegroundOnlyLocationService.kt. Kode Anda akan terlihat seperti ini:

// TODO: Step 1.2, Review the FusedLocationProviderClient.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

Seperti yang disebutkan dalam komentar sebelumnya, ini adalah class utama untuk mendapatkan update lokasi. Variabel sudah diinisialisasi untuk Anda, tetapi penting untuk meninjau kode guna memahami cara inisialisasinya. Anda akan menambahkan beberapa kode di sini nanti untuk meminta update lokasi.

Lakukan inisialisasi LocationRequest

  1. Di modul base, telusuri TODO: Step 1.3, Create a LocationRequest dalam file ForegroundOnlyLocationService.kt.
  2. Tambahkan kode berikut setelah komentar.

Kode inisialisasi LocationRequest menambahkan parameter kualitas layanan tambahan yang Anda butuhkan untuk permintaan Anda (interval, waktu tunggu maksimum, dan prioritas).

// TODO: Step 1.3, Create a LocationRequest.
locationRequest = LocationRequest.create().apply {
   // Sets the desired interval for active location updates. This interval is inexact. You
   // may not receive updates at all if no location sources are available, or you may
   // receive them less frequently than requested. You may also receive updates more
   // frequently than requested if other applications are requesting location at a more
   // frequent interval.
   //
   // IMPORTANT NOTE: Apps running on Android 8.0 and higher devices (regardless of
   // targetSdkVersion) may receive updates less frequently than this interval when the app
   // is no longer in the foreground.
   interval = TimeUnit.SECONDS.toMillis(60)

   // Sets the fastest rate for active location updates. This interval is exact, and your
   // application will never receive updates more frequently than this value.
   fastestInterval = TimeUnit.SECONDS.toMillis(30)

   // Sets the maximum time when batched location updates are delivered. Updates may be
   // delivered sooner than this interval.
   maxWaitTime = TimeUnit.MINUTES.toMillis(2)

   priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
  1. Baca komentar untuk memahami cara kerja setiap perintah.

Menginisialisasi LocationCallback

  1. Di modul base, telusuri TODO: Step 1.4, Initialize the LocationCallback dalam file ForegroundOnlyLocationService.kt.
  2. Tambahkan kode berikut setelah komentar.
// TODO: Step 1.4, Initialize the LocationCallback.
locationCallback = object : LocationCallback() {
    override fun onLocationResult(locationResult: LocationResult) {
        super.onLocationResult(locationResult)

        // Normally, you want to save a new location to a database. We are simplifying
        // things a bit and just saving it as a local variable, as we only need it again
        // if a Notification is created (when the user navigates away from app).
        currentLocation = locationResult.lastLocation

        // Notify our Activity that a new location was added. Again, if this was a
        // production app, the Activity would be listening for changes to a database
        // with new locations, but we are simplifying things a bit to focus on just
        // learning the location side of things.
        val intent = Intent(ACTION_FOREGROUND_ONLY_LOCATION_BROADCAST)
        intent.putExtra(EXTRA_LOCATION, currentLocation)
        LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)

        // Updates notification content if this service is running as a foreground
        // service.
        if (serviceRunningInForeground) {
            notificationManager.notify(
                NOTIFICATION_ID,
                generateNotification(currentLocation))
        }
    }
}

LocationCallback yang Anda buat di sini adalah callback yang akan dipanggil FusedLocationProviderClient saat update lokasi baru tersedia.

Di callback, Anda terlebih dahulu mendapatkan lokasi terbaru menggunakan objek LocationResult. Setelah itu, Anda memberi tahu Activity tentang lokasi baru menggunakan siaran lokal (jika aktif) atau Anda memperbarui Notification jika layanan ini berjalan sebagai Service latar depan.

  1. Baca komentar untuk memahami fungsi setiap bagian.

Berlangganan perubahan lokasi

Setelah menginisialisasi semuanya, Anda perlu memberi tahu FusedLocationProviderClient bahwa Anda ingin menerima update.

  1. Di modul base, telusuri Step 1.5, Subscribe to location changes dalam file ForegroundOnlyLocationService.kt.
  2. Tambahkan kode berikut setelah komentar.
// TODO: Step 1.5, Subscribe to location changes.
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())

Panggilan requestLocationUpdates() memberi tahu FusedLocationProviderClient bahwa Anda ingin menerima pembaruan lokasi.

Anda mungkin mengenali LocationRequest dan LocationCallback yang Anda tentukan sebelumnya. Parameter tersebut memberi tahu FusedLocationProviderClient parameter kualitas layanan untuk permintaan Anda dan apa yang harus dipanggil saat ada update. Terakhir, objek Looper menentukan thread untuk callback.

Anda mungkin juga melihat bahwa kode ini berada dalam pernyataan try/catch. Metode ini memerlukan pemblokiran tersebut karena SecurityException terjadi saat aplikasi Anda tidak memiliki izin untuk mengakses informasi lokasi.

Berhenti berlangganan perubahan lokasi

Saat aplikasi tidak lagi memerlukan akses ke informasi lokasi, penting untuk berhenti berlangganan dari update lokasi.

  1. Di modul base, telusuri TODO: Step 1.6, Unsubscribe to location changes dalam file ForegroundOnlyLocationService.kt.
  2. Tambahkan kode berikut setelah komentar.
// TODO: Step 1.6, Unsubscribe to location changes.
val removeTask = fusedLocationProviderClient.removeLocationUpdates(locationCallback)
removeTask.addOnCompleteListener { task ->
   if (task.isSuccessful) {
       Log.d(TAG, "Location Callback removed.")
       stopSelf()
   } else {
       Log.d(TAG, "Failed to remove Location Callback.")
   }
}

Metode removeLocationUpdates() menyiapkan tugas untuk memberi tahu FusedLocationProviderClient bahwa Anda tidak ingin lagi menerima pembaruan lokasi untuk LocationCallback. addOnCompleteListener() memberikan callback untuk penyelesaian dan menjalankan Task.

Seperti langkah sebelumnya, Anda mungkin telah melihat bahwa kode ini berada dalam pernyataan try/catch. Metode ini memerlukan pemblokiran tersebut karena SecurityException terjadi saat aplikasi Anda tidak memiliki izin untuk mengakses informasi lokasi

Anda mungkin bertanya-tanya kapan metode yang berisi kode subscribe/unsubscribe dipanggil. Fungsi ini dipicu di class utama saat pengguna mengetuk tombol. Jika Anda ingin melihatnya, lihat class MainActivity.kt.

Jalankan aplikasi

Jalankan aplikasi Anda dari Android Studio dan coba tombol lokasi.

Anda akan melihat informasi lokasi di layar output. Ini adalah aplikasi yang berfungsi penuh untuk Android 9.

2ae45c4e297e3681.png

d66089bfb532e993.png

5. Mendukung Android 10

Di bagian ini, Anda akan menambahkan dukungan untuk Android 10.

Aplikasi Anda sudah berlangganan perubahan lokasi, jadi tidak banyak yang perlu dilakukan.

Faktanya, yang harus Anda lakukan hanyalah menentukan bahwa layanan latar depan Anda digunakan untuk tujuan lokasi.

SDK Target 29

  1. Di modul base, telusuri TODO: Step 2.1, Target Android 10 and then Android 11. dalam file build.gradle.
  2. Buat perubahan berikut:
  3. Tetapkan targetSdkVersion ke 29.

Kode Anda akan terlihat seperti ini:

android {
   // TODO: Step 2.1, Target Android 10 and then Android 11.
   compileSdkVersion 29
   defaultConfig {
       applicationId "com.example.android.whileinuselocation"
       minSdkVersion 26
       targetSdkVersion 29
       versionCode 1
       versionName "1.0"
   }
...
}

Setelah melakukannya, Anda akan diminta untuk menyinkronkan project. Klik Sync Now.

153f70847e0ec320.png

Setelah itu, aplikasi Anda hampir siap untuk Android 10.

Menambahkan Jenis Layanan Latar Depan

Di Android 10, Anda harus menyertakan jenis layanan latar depan jika memerlukan akses lokasi saat digunakan. Dalam kasus Anda, izin ini digunakan untuk mendapatkan informasi lokasi.

Dalam modul base, telusuri TODO: 2.2, Add foreground service type di AndroidManifest.xml, lalu tambahkan kode berikut ke elemen <service>:

android:foregroundServiceType="location"

Kode Anda akan terlihat seperti ini:

<application>
   ...

   <!-- Foreground services in Android 10+ require type. -->
   <!-- TODO: 2.2, Add foreground service type. -->
   <service
       android:name="com.example.android.whileinuselocation.ForegroundOnlyLocationService"
       android:enabled="true"
       android:exported="false"
       android:foregroundServiceType="location" />
</application>

Selesai! Aplikasi Anda mendukung lokasi Android 10 untuk "saat digunakan" dengan mengikuti praktik terbaik untuk lokasi di Android.

Jalankan aplikasi

Jalankan aplikasi Anda dari Android Studio dan coba tombol lokasi.

Semuanya akan berfungsi seperti sebelumnya, tetapi sekarang berfungsi di Android 10. Jika Anda belum menyetujui izin untuk lokasi sebelumnya, Anda akan melihat layar izin sekarang.

6a1029175b467c77.png

c7c1d226e49a121.png

39a262b66a275f66.png

6. Mendukung Android 11

Di bagian ini, Anda akan menargetkan Android 11.

Kabar baiknya, Anda tidak perlu mengubah file apa pun kecuali file build.gradle.

SDK Target 11

  1. Di modul base, telusuri TODO: Step 2.1, Target SDK dalam file build.gradle.
  2. Buat perubahan berikut:
  3. compileSdkVersion hingga 30
  4. targetSdkVersion hingga 30

Kode Anda akan terlihat seperti ini:

android {
   TODO: Step 2.1, Target Android 10 and then Android 11.
   compileSdkVersion 30
   defaultConfig {
       applicationId "com.example.android.whileinuselocation"
       minSdkVersion 26
       targetSdkVersion 30
       versionCode 1
       versionName "1.0"
   }
...
}

Setelah melakukannya, Anda akan diminta untuk menyinkronkan project. Klik Sync Now.

153f70847e0ec320.png

Setelah itu, aplikasi Anda siap untuk Android 11.

Jalankan aplikasi

Jalankan aplikasi Anda dari Android Studio dan coba klik tombol.

Semuanya akan berfungsi seperti sebelumnya, tetapi sekarang berfungsi di Android 11. Jika Anda belum menyetujui izin untuk lokasi sebelumnya, Anda akan melihat layar izin sekarang.

73d8cc88c5877c25.png

cc98fac6e089bc4.png

7. Strategi lokasi untuk Android

Dengan memeriksa dan meminta izin lokasi sesuai cara yang ditunjukkan dalam codelab ini, aplikasi Anda dapat berhasil melacak tingkat aksesnya terkait lokasi perangkat.

Halaman ini mencantumkan beberapa praktik terbaik utama terkait izin akses lokasi. Untuk mengetahui informasi selengkapnya tentang cara menjaga keamanan data pengguna, lihat Praktik terbaik izin aplikasi.

Hanya meminta izin yang Anda perlukan

Minta izin hanya jika diperlukan. Contoh:

  • Jangan meminta izin lokasi saat aplikasi dimulai, kecuali benar-benar diperlukan.
  • Jika aplikasi Anda menargetkan Android 10 atau yang lebih baru dan Anda memiliki layanan latar depan, deklarasikan foregroundServiceType "location" dalam manifes.
  • Jangan meminta izin akses lokasi di latar belakang kecuali jika Anda memiliki kasus penggunaan yang valid seperti yang dijelaskan dalam Akses yang Lebih Aman dan Transparan ke Lokasi Pengguna.

Mendukung degradasi halus jika izin tidak diberikan

Untuk mempertahankan pengalaman pengguna yang baik, desain aplikasi Anda agar dapat secara halus menangani situasi berikut:

  • Aplikasi Anda tidak memiliki akses ke informasi lokasi.
  • Aplikasi Anda tidak memiliki akses ke informasi lokasi saat berjalan di latar belakang.

8. Selamat

Anda telah mempelajari cara menerima pembaruan lokasi di Android, dengan mempertimbangkan praktik terbaik.

Pelajari lebih lanjut