Pembatasan wilayah menggabungkan kemampuan penentuan lokasi pengguna saat ini dan kemampuan penentuan kedekatan lokasi pengguna dengan lokasi tertentu. Untuk menandai lokasi tertentu, Anda harus menentukan lintang dan bujurnya. Untuk menyesuaikan kedekatan lokasi, Anda harus menambahkan radius. Lintang, bujur, dan radius menentukan pembatasan wilayah, yang menciptakan area lingkaran, atau pembatas, di sekitar lokasi tertentu.
Anda dapat memiliki beberapa pembatasan wilayah aktif, dengan batas 100 per pengguna perangkat per aplikasi. Untuk setiap pembatasan wilayah, Anda dapat meminta Layanan Lokasi untuk mengirimi Anda peristiwa masuk dan keluar, atau menentukan durasi di area pembatasan wilayah untuk menunggu, atau diam, sebelum memicu suatu peristiwa. Anda dapat membatasi durasi pembatasan wilayah dengan menentukan durasi akhir dalam milidetik. Setelah pembatasan wilayah berakhir, Layanan Lokasi otomatis akan menghapusnya.
Tutorial ini menunjukkan cara menambahkan dan menghapus pembatasan wilayah, kemudian mendeteksi transisi pembatasan wilayah
menggunakan BroadcastReceiver
.
Catatan: Di perangkat Wear, Geofencing API tidak memanfaatkan secara efisien daya. Kami tidak merekomendasikan API ini di Wear. {i>Read<i} Hemat daya dan baterai untuk mengetahui informasi selengkapnya.
Menyiapkan pemantauan pembatasan wilayah
Langkah pertama dalam meminta pemantauan pembatasan wilayah adalah meminta izin yang diperlukan. Untuk menggunakan pembatasan wilayah, aplikasi Anda harus meminta izin berikut:
-
ACCESS_FINE_LOCATION
-
ACCESS_BACKGROUND_LOCATION
jika aplikasi Anda menargetkan Android 10 (API level 29) atau yang lebih baru
Untuk mempelajarinya lebih lanjut, lihat panduan cara meminta izin akses lokasi.
Jika Anda ingin menggunakan BroadcastReceiver
untuk mendeteksi transisi pembatasan wilayah,
tambahkan elemen yang menentukan nama layanan. Elemen ini harus berupa
turunan dari elemen
<application>
:
<application android:allowBackup="true"> ... <receiver android:name=".GeofenceBroadcastReceiver"/> <application/>
Untuk mengakses location API, Anda harus membuat instance klien Pembatasan Wilayah. Untuk mempelajari cara menghubungkan klien Anda:
Kotlin
lateinit var geofencingClient: GeofencingClient override fun onCreate(savedInstanceState: Bundle?) { // ... geofencingClient = LocationServices.getGeofencingClient(this) }
Java
private GeofencingClient geofencingClient; @Override public void onCreate(Bundle savedInstanceState) { // ... geofencingClient = LocationServices.getGeofencingClient(this); }
Membuat dan menambahkan pembatasan wilayah
Aplikasi Anda harus membuat dan menambahkan pembatasan wilayah menggunakan class builder location API untuk
membuat objek Pembatasan Wilayah, dan class praktis untuk menambahkannya. Selain itu, untuk menangani
intent yang dikirim dari Layanan Lokasi saat transisi pembatasan wilayah terjadi, Anda dapat menentukan
PendingIntent
seperti yang ditunjukkan dalam bagian ini.
Catatan: Pada perangkat pengguna tunggal, ada batas 100 pembatasan wilayah per aplikasi. Untuk perangkat multi-pengguna, batasnya sebanyak 100 pembatasan wilayah per aplikasi per pengguna perangkat.
Membuat objek pembatasan wilayah
Pertama, gunakan
Geofence.Builder
untuk membuat pembatasan wilayah, dengan menyetel radius, durasi, dan
jenis transisi untuk pembatasan wilayah. Misalnya, untuk mengisi objek daftar:
Kotlin
geofenceList.add(Geofence.Builder() // Set the request ID of the geofence. This is a string to identify this // geofence. .setRequestId(entry.key) // Set the circular region of this geofence. .setCircularRegion( entry.value.latitude, entry.value.longitude, Constants.GEOFENCE_RADIUS_IN_METERS ) // Set the expiration duration of the geofence. This geofence gets automatically // removed after this period of time. .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) // Set the transition types of interest. Alerts are only generated for these // transition. We track entry and exit transitions in this sample. .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT) // Create the geofence. .build())
Java
geofenceList.add(new Geofence.Builder() // Set the request ID of the geofence. This is a string to identify this // geofence. .setRequestId(entry.getKey()) .setCircularRegion( entry.getValue().latitude, entry.getValue().longitude, Constants.GEOFENCE_RADIUS_IN_METERS ) .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build());
Contoh ini menarik data dari file konstanta. Dalam praktik nyata, aplikasi mungkin secara dinamis akan membuat pembatasan wilayah berdasarkan lokasi pengguna.
Menentukan pembatasan wilayah dan pemicu awal
Cuplikan berikut menggunakan class
GeofencingRequest
dan class
GeofencingRequestBuilder
bertingkatnya untuk
menentukan pembatasan wilayah yang akan dipantau dan untuk menyetel cara memicu peristiwa pembatasan wilayah terkait:
Kotlin
private fun getGeofencingRequest(): GeofencingRequest { return GeofencingRequest.Builder().apply { setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) addGeofences(geofenceList) }.build() }
Java
private GeofencingRequest getGeofencingRequest() { GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); builder.addGeofences(geofenceList); return builder.build(); }
Contoh berikut menunjukkan penggunaan dua pemicu pembatasan wilayah. Transisi
GEOFENCE_TRANSITION_ENTER
dipicu saat perangkat memasuki pembatasan wilayah, dan transisi
GEOFENCE_TRANSITION_EXIT
dipicu saat perangkat keluar dari pembatasan wilayah. Menentukan
INITIAL_TRIGGER_ENTER
akan memberi tahu Layanan lokasi bahwa
GEOFENCE_TRANSITION_ENTER
harus dipicu jika perangkat sudah berada di dalam pembatasan wilayah.
Dalam banyak kasus, mungkin lebih baik gunakan
INITIAL_TRIGGER_DWELL
,
yang memicu peristiwa hanya saat pengguna berhenti selama durasi yang ditentukan dalam pembatasan wilayah.
Pendekatan ini dapat membantu mengurangi "notifikasi spam" yang dihasilkan dari notifikasi dalam jumlah banyak saat
perangkat masuk dan keluar sebentar dari pembatasan wilayah. Strategi lain untuk mendapatkan hasil terbaik dari
pembatasan wilayah Anda adalah menetapkan radius minimum sejauh 100 meter. Cara ini membantu memperhitungkan akurasi lokasi
jaringan Wi-Fi biasa, dan juga membantu mengurangi konsumsi daya perangkat.
Menentukan penerima siaran untuk transisi pembatasan wilayah
Suatu Intent
yang dikirim dari Layanan Lokasi dapat memicu berbagai tindakan di
aplikasi Anda, tetapi Anda tidak boleh membiarkannya memulai aktivitas atau fragmen, karena komponen
seharusnya hanya terlihat sebagai respons terhadap tindakan pengguna. Dalam banyak kasus, BroadcastReceiver
adalah cara yang baik untuk menangani transisi pembatasan wilayah. Suatu
BroadcastReceiver
akan mendapatkan update saat suatu peristiwa terjadi, seperti
transisi masuk atau keluar dari pembatasan wilayah, dan dapat memulai tugas latar belakang yang berjalan
lama.
Cuplikan berikut menunjukkan cara
menentukan PendingIntent
yang memulai BroadcastReceiver
:
Kotlin
class MainActivity : AppCompatActivity() { // ... private val geofencePendingIntent: PendingIntent by lazy { val intent = Intent(this, GeofenceBroadcastReceiver::class.java) // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling // addGeofences() and removeGeofences(). PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } }
Java
public class MainActivity extends AppCompatActivity { // ... private PendingIntent getGeofencePendingIntent() { // Reuse the PendingIntent if we already have it. if (geofencePendingIntent != null) { return geofencePendingIntent; } Intent intent = new Intent(this, GeofenceBroadcastReceiver.class); // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when // calling addGeofences() and removeGeofences(). geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent. FLAG_UPDATE_CURRENT); return geofencePendingIntent; }
Menambahkan pembatasan wilayah
Untuk menambahkan pembatasan wilayah, gunakan metode
.
Berikan objek GeofencingClient.addGeofences()
GeofencingRequest
, dan PendingIntent
.
Cuplikan berikut menunjukkan pemrosesan hasilnya:
Kotlin
geofencingClient?.addGeofences(getGeofencingRequest(), geofencePendingIntent)?.run { addOnSuccessListener { // Geofences added // ... } addOnFailureListener { // Failed to add geofences // ... } }
Java
geofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent()) .addOnSuccessListener(this, new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { // Geofences added // ... } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Failed to add geofences // ... } });
Menangani transisi pembatasan wilayah
Saat mendeteksi bahwa pengguna telah masuk atau keluar dari pembatasan wilayah, Layanan Lokasi akan
mengirimkan Intent
yang ada di dalam PendingIntent
yang Anda sertakan dalam permintaan untuk menambahkan pembatasan wilayah. Penerima siaran seperti
GeofenceBroadcastReceiver
mengetahui bahwa Intent
dipanggil, kemudian
dapat memperoleh peristiwa pembatasan wilayah dari intent, menentukan jenis transisi Pembatasan Wilayah,
dan menentukan pembatasan wilayah yang ditetapkan mana yang dipicu. Penerima siaran
dapat mengarahkan aplikasi agar mulai menjalankan tugas di latar belakang atau, jika
diinginkan, mengirim notifikasi sebagai output.
Catatan: Di Android 8.0 (API level 26) dan yang lebih baru, jika aplikasi berjalan di latar belakang sambil memantau pembatasan wilayah, perangkat akan merespons peristiwa pembatasan wilayah setiap beberapa menit. Untuk mempelajari cara menyesuaikan aplikasi Anda dengan batas respons ini, baca Batas Lokasi Latar Belakang.
Cuplikan berikut menunjukkan cara menentukan
BroadcastReceiver
yang memposting notifikasi jika transisi pembatasan wilayah terjadi. Saat pengguna
mengklik notifikasi, aktivitas utama aplikasi akan muncul:
Kotlin
class GeofenceBroadcastReceiver : BroadcastReceiver() { // ... override fun onReceive(context: Context?, intent: Intent?) { val geofencingEvent = GeofencingEvent.fromIntent(intent) if (geofencingEvent.hasError()) { val errorMessage = GeofenceStatusCodes .getStatusCodeString(geofencingEvent.errorCode) Log.e(TAG, errorMessage) return } // Get the transition type. val geofenceTransition = geofencingEvent.geofenceTransition // Test that the reported transition was of interest. if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER | geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { // Get the geofences that were triggered. A single event can trigger // multiple geofences. val triggeringGeofences = geofencingEvent.triggeringGeofences // Get the transition details as a String. val geofenceTransitionDetails = getGeofenceTransitionDetails( this, geofenceTransition, triggeringGeofences ) // Send notification and log the transition details. sendNotification(geofenceTransitionDetails) Log.i(TAG, geofenceTransitionDetails) } else { // Log the error. Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition)) } } }
Java
public class GeofenceBroadcastReceiver extends BroadcastReceiver { // ... protected void onReceive(Context context, Intent intent) { GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); if (geofencingEvent.hasError()) { String errorMessage = GeofenceStatusCodes .getStatusCodeString(geofencingEvent.getErrorCode()); Log.e(TAG, errorMessage); return; } // Get the transition type. int geofenceTransition = geofencingEvent.getGeofenceTransition(); // Test that the reported transition was of interest. if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { // Get the geofences that were triggered. A single event can trigger // multiple geofences. List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences(); // Get the transition details as a String. String geofenceTransitionDetails = getGeofenceTransitionDetails( this, geofenceTransition, triggeringGeofences ); // Send notification and log the transition details. sendNotification(geofenceTransitionDetails); Log.i(TAG, geofenceTransitionDetails); } else { // Log the error. Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition)); } } }
Setelah mendeteksi peristiwa transisi melalui PendingIntent
,
BroadcastReceiver
akan mendapatkan jenis transisi pembatasan wilayah dan
menguji apakah peristiwa tersebut termasuk salah satu yang digunakan
aplikasi untuk memicu
notifikasi -- dalam
hal ini entah GEOFENCE_TRANSITION_ENTER
ataupun GEOFENCE_TRANSITION_EXIT
. Layanan tersebut kemudian mengirimkan notifikasi dan mencatat detail transisi.
Menghentikan pemantauan pembatasan wilayah
Penghentian pemantauan pembatasan wilayah saat tidak lagi diperlukan atau diinginkan dapat membantu menghemat daya
baterai dan siklus CPU pada perangkat. Anda dapat menghentikan pemantauan
pembatasan wilayah dalam aktivitas utama yang digunakan untuk menambahkan dan menghapus pembatasan wilayah; penghapusan pembatasan wilayah akan menghentikannya
secara langsung. API menyediakan metode untuk
menghapus pembatasan wilayah dengan ID permintaan, atau dengan menghapus pembatasan wilayah yang terkait dengan
PendingIntent
tertentu.
Cuplikan berikut menghapus pembatasan wilayah dengan PendingIntent
, yang akan menghentikan semua
notifikasi berikutnya saat perangkat masuk atau keluar dari pembatasan wilayah yang telah ditambahkan sebelumnya:
Kotlin
geofencingClient?.removeGeofences(geofencePendingIntent)?.run { addOnSuccessListener { // Geofences removed // ... } addOnFailureListener { // Failed to remove geofences // ... } }
Java
geofencingClient.removeGeofences(getGeofencePendingIntent()) .addOnSuccessListener(this, new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { // Geofences removed // ... } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Failed to remove geofences // ... } });
Anda dapat menggabungkan pembatasan wilayah dengan fitur kemampuan penentuan lokasi lainnya, seperti pembaruan lokasi berkala. Untuk informasi selengkapnya, lihat tutorial lain di kelas ini.
Menggunakan praktik terbaik untuk pembatasan wilayah
Bagian ini menguraikan rekomendasi untuk menggunakan pembatasan wilayah dengan location API bagi Android.
Mengurangi konsumsi daya
Anda dapat menggunakan teknik berikut untuk mengoptimalkan konsumsi daya di aplikasi Anda yang menggunakan pembatasan wilayah:
Tetapkan responsivitas notifikasi ke nilai yang lebih tinggi. Hal tersebut akan mengoptimalkan konsumsi daya dengan menambah latensi notifikasi pembatasan wilayah. Misalnya, jika Anda menyetel nilai respons selama lima menit, aplikasi Anda hanya akan memeriksa notifikasi masuk atau keluar satu kali setiap lima menit. Menyetel nilai yang lebih rendah tidak selalu berarti bahwa pengguna akan mendapat notifikasi dalam periode waktu tersebut (misalnya, jika Anda menyetel nilai 5 detik, mungkin butuh waktu sedikit lebih lama untuk menerima notifikasi).
Gunakan radius pembatasan wilayah yang lebih besar untuk lokasi tempat pengguna menghabiskan banyak waktu, seperti rumah atau kantor. Radius yang lebih besar tidak akan secara langsung mengurangi konsumsi daya, tetapi akan mengurangi frekuensi pemeriksaan masuk atau keluar oleh aplikasi, yang pada praktiknya akan menurunkan konsumsi daya secara keseluruhan.
Memilih radius optimal untuk pembatasan wilayah Anda
Untuk hasil terbaik, radius minimum pembatasan wilayah harus disetel 100 - 150 meter. Jika Wi-Fi tersedia, akurasi lokasi biasanya antara 20 - 50 meter. Jika lokasi dalam ruangan tersedia, rentang akurasi dapat sekecil 5 meter. Kecuali jika Anda tahu ada lokasi dalam ruangan yang tersedia di dalam pembatasan wilayah, anggaplah akurasi lokasi Wi-Fi sekitar 50 meter.
Jika lokasi Wi-Fi tidak tersedia (misalnya, ketika Anda mengemudi di daerah pedesaan) akurasi lokasi akan menurun. Rentang akurasi dapat mencapai beberapa ratus meter hingga beberapa kilometer. Dalam kasus seperti ini, Anda harus membuat pembatasan wilayah dengan radius yang lebih besar.
Menjelaskan kepada pengguna mengapa aplikasi Anda menggunakan pembatasan wilayah
Karena aplikasi Anda mengakses lokasi di latar belakang saat Anda menggunakan pembatasan wilayah, pertimbangkan cara aplikasi memberikan manfaat kepada pengguna. Jelaskan kepada mereka dengan jelas mengapa aplikasi Anda memerlukan akses ini untuk meningkatkan pemahaman pengguna dan transparansi.
Untuk informasi selengkapnya tentang praktik terbaik terkait akses lokasi, termasuk pembatasan wilayah, lihat halaman praktik terbaik privasi.
Menggunakan jenis transisi diam untuk mengurangi notifikasi spam
Jika Anda menerima banyak notifikasi saat berkendara sebentar melewati suatu pembatasan wilayah, cara terbaik untuk
mengurangi notifikasi adalah dengan menggunakan jenis transisi
GEOFENCE_TRANSITION_DWELL
, bukan
GEOFENCE_TRANSITION_ENTER
. Dengan cara ini, notifikasi diam akan dikirim hanya saat pengguna berhenti
di dalam pembatasan wilayah selama jangka waktu tertentu. Anda dapat memilih durasinya dengan menyetel
penundaan loitering.
Mendaftarkan ulang pembatasan wilayah hanya jika diperlukan
Pembatasan wilayah terdaftar disimpan dalam proses com.google.process.location
yang dimiliki oleh
paket com.google.android.gms
.
Aplikasi tidak perlu melakukan apa pun untuk menangani peristiwa berikut, karena sistem akan
memulihkan pembatasan wilayah setelah peristiwa ini:
- Layanan Google Play diupgrade.
- Layanan Google Play dimatikan dan dimulai ulang oleh sistem karena pembatasan resource.
- Proses lokasi terhenti.
Aplikasi harus mendaftarkan ulang pembatasan wilayah jika masih diperlukan setelah peristiwa berikut, karena sistem tidak dapat memulihkan pembatasan wilayah dalam kasus berikut:
- Perangkat dimulai ulang. Aplikasi harus memproses tindakan booting lengkap perangkat, kemudian mendaftarkan ulang pembatasan wilayah yang diperlukan.
- Aplikasi dihapus dan diinstal ulang.
- Data aplikasi dihapus.
- Data layanan Google Play dihapus.
- Aplikasi menerima pemberitahuan
GEOFENCE_NOT_AVAILABLE
. Ini biasanya terjadi setelah NLP (Penyedia Lokasi Jaringan Android) dinonaktifkan.
Memecahkan masalah peristiwa masuk pembatasan wilayah
Jika pembatasan wilayah tidak dipicu saat perangkat memasuki pembatasan wilayah
(notifikasi
GEOFENCE_TRANSITION_ENTER
tidak dipicu), terlebih dahulu pastikan bahwa pembatasan wilayah Anda terdaftar dengan benar seperti yang
dijelaskan dalam panduan ini.
Berikut adalah beberapa kemungkinan alasan notifikasi tidak berfungsi seperti yang diharapkan:
- Lokasi akurat tidak tersedia dalam pembatasan wilayah Anda atau pembatasan wilayah Anda terlalu kecil. Di sebagian besar perangkat, layanan pembatasan wilayah hanya menggunakan lokasi jaringan untuk memicu pembatasan wilayah. Layanan menggunakan pendekatan ini karena lokasi jaringan mengonsumsi daya jauh lebih sedikit, perlu waktu lebih sedikit untuk mendapatkan lokasi diskret, dan yang paling penting, tersedia di dalam ruangan.
Wi-Fi dinonaktifkan pada perangkat. Mengaktifkan Wi-Fi dapat meningkatkan akurasi lokasi secara signifikan, sehingga jika Wi-Fi dimatikan, aplikasi Anda mungkin tidak akan pernah menerima notifikasi pembatasan wilayah, bergantung pada beberapa setelan termasuk radius pembatasan wilayah, model perangkat, atau versi Android. Mulai dari Android 4.3 (API level 18), kami menambahkan kemampuan "Mode hanya pemindaian Wi-Fi" yang memungkinkan pengguna untuk menonaktifkan Wi-Fi, tetapi masih mendapatkan lokasi jaringan yang baik. Praktik yang baik adalah meminta pengguna dan memberikan pintasan bagi pengguna untuk mengaktifkan mode Wi-Fi atau hanya pemindaian Wi-Fi jika keduanya dinonaktifkan. Gunakan SettingsClient untuk memastikan bahwa setelan sistem perangkat telah dikonfigurasi dengan benar untuk deteksi lokasi yang optimal.
Catatan: Jika aplikasi Anda menargetkan Android 10 (API level 29) atau yang lebih baru, Anda tidak dapat memanggil
WifiManager.setEnabled()
secara langsung, kecuali jika aplikasi Anda adalah aplikasi sistem atau pengontrol kebijakan perangkat (DPC). Sebagai gantinya, gunakan panel setelan.- Tidak ada konektivitas jaringan yang andal dalam pembatasan wilayah Anda. Jika tidak ada koneksi data yang dapat diandalkan, notifikasi mungkin tidak dihasilkan. Hal ini dikarenakan layanan pembatasan wilayah bergantung pada penyedia lokasi jaringan, sedangkan penyedia tersebut memerlukan koneksi data.
- Notifikasi dapat muncul terlambat. Layanan pembatasan wilayah tidak terus-menerus mencari lokasi, jadi akan ada sedikit latensi saat menerima pemberitahuan. Biasanya latensi terjadi kurang dari 2 menit, bahkan kurang jika perangkat telah bergerak. Jika Batas Lokasi Latar Belakang berlaku, latensi rata-rata berlangsung sekitar 2-3 menit. Jika perangkat tidak bergerak selama periode waktu yang cukup lama, latensi dapat meningkat (hingga 6 menit).
Referensi lainnya
Untuk mempelajari Pembatasan Wilayah lebih lanjut, lihat materi berikut:
Contoh
Aplikasi contoh untuk membuat dan memantau pembatasan wilayah.