Menerima pembaruan lokasi di Android dengan Kotlin

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

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

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

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

Android 10

Android 11

Dalam codelab ini, Anda akan mempelajari cara menerima pembaruan lokasi dan cara mendukung lokasi di semua versi Android, terutama Android 10 dan 11. Di akhir codelab, Anda akan dapat memiliki aplikasi yang mengikuti praktik terbaik saat ini untuk mengambil pembaruan 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 sedang digunakan).
  • Memodifikasi aplikasi yang ada untuk menambahkan dukungan guna meminta akses lokasi dengan menambahkan kode untuk berlangganan dan berhenti berlangganan lokasi.
  • Menambahkan 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

Meng-clone repositori project awal

Untuk membantu Anda memulai secepatnya, Anda dapat membuat project awal ini. Jika Anda sudah menginstal Git, cukup jalankan perintah berikut:

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

Kunjungi halaman GitHub secara langsung.

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

Download zip

Mengimpor project

Buka Android Studio, pilih "Open an existing Android Studio project" dari layar sambutan, dan 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.)

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 jangka waktu ini, Anda akan melihat pesan berikut di status bar di bagian bawah Android Studio:

Tunggu sampai Android Studio selesai mengindeks dan membuat 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 siap untuk meminta lokasi di aplikasi. Gunakan modul base sebagai titik awal. Di setiap langkah, tambahkan kode ke modul base. Pada saat Anda selesai dengan codelab ini, kode dalam 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, dan mempromosikan dirinya sendiri 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 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 versi yang lebih tinggi.)
  2. Di toolbar, pilih konfigurasi base dari pemilih drop-down, lalu klik Jalankan:


  1. Perhatikan bahwa aplikasi berikut muncul di perangkat Anda:


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

Konsep

Fokus codelab ini adalah untuk menunjukkan kepada Anda cara menerima pembaruan lokasi, dan pada 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. Lihatlah apa artinya:

  • Izinkan hanya saat aplikasi digunakan
  • Opsi ini adalah opsi yang direkomendasikan untuk sebagian besar aplikasi. Juga dikenal sebagai akses "saat digunakan" atau "latar depan saja", opsi ini ditambahkan di Android 10 dan memungkinkan developer mengambil lokasi hanya saat aplikasi aktif digunakan. Aplikasi dianggap aktif jika salah satu hal berikut terjadi:
  • Aktivitas terlihat.
  • Layanan latar depan berjalan dengan notifikasi yang sedang berlangsung.
  • Satu kali
  • Ditambahkan di Android 11, opsi ini sama dengan Izinkan hanya saat aplikasi digunakan, tetapi untuk waktu yang terbatas. Untuk mengetahui informasi selengkapnya, lihat Izin satu kali.
  • 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 versi 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 ini merupakan kasus penggunaan yang lebih jarang. Namun, jika Anda memiliki kasus penggunaan yang valid dan ingin memahami cara menangani lokasi sepanjang waktu dengan benar, termasuk mengakses lokasi di latar belakang, tinjau contoh LocationUpdatesBackgroundKotlin.

Layanan, layanan latar depan, dan binding

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

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

Karena codelab ini hanya berfokus pada pembaruan lokasi, Anda dapat menemukan semua kode yang Anda butuhkan di class ForegroundOnlyLocationService.kt. Anda dapat menjelajahi class tersebut dan MainActivity.kt untuk melihat cara keduanya berfungsi bersama.

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

Izin

Untuk 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 dapat meminta akses ke lokasi pada saat runtime.

Izin tersebut mencakup kasus Satu kali dan Hanya izinkan saat menggunakan aplikasi saat aplikasi digunakan di perangkat yang menjalankan Android 10 atau yang lebih baru.

Lokasi

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

Lihat class utama:

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

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

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

Codelab ini bertujuan untuk menunjukkan cara menerima pembaruan lokasi, bukan cara meminta izin akses lokasi, sehingga kode berbasis izin sudah ditulis untuk Anda. Jangan ragu untuk melewatinya jika Anda sudah memahaminya.

Berikut adalah sorotan izin (tidak ada tindakan yang perlu dilakukan untuk bagian ini):

  1. Mendeklarasikan 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 belum menerima izin, minta akses.
  3. Tangani pilihan izin pengguna. (Anda dapat melihat kode ini di MainActivity.kt.)

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

Untuk informasi selengkapnya, lihat Ringkasan izin.

Sekarang, mulailah menulis beberapa kode lokasi.

Meninjau variabel utama yang diperlukan untuk pembaruan lokasi

Dalam modul base, telusuri TODO: Step 1.1, Review variables dalam

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 digunakan untuk menerima pembaruan 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

Meninjau inisialisasi FusedLocationProviderClient

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

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

Seperti yang disebutkan dalam komentar sebelumnya, ini adalah class utama untuk mendapatkan pembaruan lokasi. Variabel ini telah diinisialisasikan, tetapi Anda harus meninjau kode untuk memahami cara variabel diinisialisasi. Anda dapat menambahkan beberapa kode di sini nanti untuk meminta pembaruan lokasi.

Menginisialisasi LocationRequest

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

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

// TODO: Step 1.3, Create a LocationRequest.
locationRequest = LocationRequest().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 semua komentar untuk memahami cara kerjanya.

Menginisialisasi LocationCallback

  1. Dalam 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)

       if (locationResult?.lastLocation != null) {

           // 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 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))
           }
       } else {
           Log.d(TAG, "Location information isn't available.")
       }
   }
}

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

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

  1. Baca komentar untuk memahami fungsi setiap bagian.

Berlangganan perubahan lokasi

Setelah melakukan inisialisasi semuanya, Anda harus memberi tahu FusedLocationProviderClient bahwa Anda ingin menerima update.

  1. Dalam 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.myLooper())

Panggilan requestLocationUpdates() memungkinkan FusedLocationProviderClient mengetahui bahwa Anda ingin menerima pembaruan lokasi.

Anda mungkin mengenali LocationRequest dan LocationCallback yang Anda tentukan sebelumnya. Hal tersebut memungkinkan FusedLocationProviderClient mengetahui parameter kualitas layanan untuk permintaan Anda dan hal yang harus dipanggilnya saat memiliki update. Terakhir, objek Looper menentukan thread untuk callback.

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

Berhenti berlangganan dari perubahan lokasi

Jika aplikasi tidak lagi memerlukan akses ke informasi lokasi, penting untuk berhenti berlangganan dari pembaruan lokasi.

  1. Dalam 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 melihat bahwa kode ini berada dalam pernyataan try/catch. Metode ini memerlukan pemblokiran seperti itu karena SecurityException terjadi saat aplikasi Anda tidak memiliki izin untuk mengakses informasi lokasi

Anda mungkin bertanya-tanya kapan metode yang berisi kode berlangganan/berhenti berlangganan dipanggil. Pemicu tersebut dipicu di kelas utama ketika 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 sepenuhnya untuk Android 9.

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

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

Bahkan, Anda hanya perlu menentukan bahwa layanan latar depan Anda digunakan untuk tujuan lokasi.

Target SDK 29

  1. Dalam modul base, telusuri TODO: Step 2.1, Target SDK 10 dalam file build.gradle.
  2. Buat perubahan ini:
  1. Tetapkan compileSdkVersion ke 29.
  2. Tetapkan buildToolsVersion ke "29.0.3".
  3. Tetapkan targetSdkVersion ke 29.

Kode akan terlihat seperti berikut:

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

Setelah melakukannya, Anda akan diminta untuk menyinkronkan project. Klik Sinkronkan Sekarang.

Setelah itu, aplikasi Anda hampir siap untuk Android 10.

Tambahkan Jenis Layanan Latar Depan

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

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

android:foregroundServiceType="location"

Kode akan terlihat seperti berikut:

<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, namun kini berfungsi di Android 10. Jika sebelumnya Anda tidak menyetujui izin untuk lokasi, sekarang Anda akan melihat layar izin.

Di bagian ini, Anda menargetkan Android 11.

Kabar baik, Anda tidak perlu melakukan perubahan pada file apa pun kecuali file build.gradle.

Menargetkan SDK R

  1. Dalam modul base, telusuri TODO: Step 2.1, Target SDK dalam file build.gradle.
  2. Buat perubahan ini:
  1. compileSdkVersion ke "android-R"
  2. targetSdkVersion ke "R"

Kode akan terlihat seperti berikut:

android {
   // TODO: Step 2.1, Target Android 10.
   compileSdkVersion "android-R"
   buildToolsVersion "29.0.2"
   defaultConfig {
       applicationId "com.example.android.whileinuselocation"
       minSdkVersion 26
       targetSdkVersion "R"
       versionCode 1
       versionName "1.0"
   }
...
}

Setelah melakukannya, Anda akan diminta untuk menyinkronkan project. Klik Sinkronkan Sekarang.

Setelah itu, aplikasi Anda siap untuk Android 11.

Jalankan aplikasi

Jalankan aplikasi Anda dari Android Studio dan coba klik tombolnya.

Semuanya akan berfungsi seperti sebelumnya, namun kini berfungsi di Android 11. Jika sebelumnya Anda tidak menyetujui izin untuk lokasi, sekarang Anda akan melihat layar izin.

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

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

Hanya meminta izin yang Anda perlukan

Minta izin hanya jika diperlukan. Misalnya:

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

Dukung degradasi halus jika izin tidak diberikan

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

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

Anda telah mempelajari cara menerima pembaruan lokasi di Android, dengan memperhatikan praktik terbaik!

Pelajari lebih lanjut