When geofences are not triggering on iOS, the cause is almost always one of a short list: the app lacks Always authorization, the device was already inside the region when you added it, the radius is too small for iOS to detect a crossing, the app hit the 20 region limit, or the test did not wait long enough. iOS geofencing works well, but it reports crossings on its own schedule. This guide explains how region monitoring decides when to fire, and how to debug a Capacitor app using @capgo/background-geolocation, yang termasuk geofencing asli pada iOS dan Android.
Bagaimana Pengawasan Wilayah iOS Berfungsi
On iOS, geofence adalah CLCircularRegion objek yang terdaftar dengan Core Location. Setelah terdaftar, sistem operasi memantau mereka, bukan aplikasi Anda. Aplikasi Anda dapat ditangguhkan atau tidak berjalan dan iOS masih mengikuti wilayah, menggunakan kombinasi menara sel, Wi-Fi, dan GPS untuk menjaga penggunaan baterai rendah.
Ketika iOS memutuskan perangkat melintasi batas, ia mengirimkan event masuk atau keluar ke aplikasi, meluncurkannya di latar belakang jika perlu dan diizinkan. Beberapa aturan mengontrol keputusan tersebut:
- iOS tidak melaporkan melintasi saat perangkat menyentuh batas. Panduan Apple adalah bahwa perangkat harus melintasi, bergerak jarak minimum melewati batas, dan berada di sana selama minimal sekitar 20 detik sebelum event disampaikan. Ini menghindari menembak pada getaran GPS.
- Kemampuan lokasi untuk pemantauan wilayah tergantung pada apa yang ada di sekitar. Di kota dengan Wi-Fi padat, itu bisa cepat. Di jalan desa, itu bisa memakan menit.
- Event hanya untuk transisi. Berada di dalam wilayah ketika pemantauan dimulai tidak dihitung sebagai masuk.
Set up geofencing di sebuah Capacitor aplikasi
Instal plugin dan konfigurasi kunci iOS:
bun add @capgo/background-geolocation
bunx cap sync
<key>NSLocationWhenInUseUsageDescription</key>
<string>We use your location to detect when you arrive at a store.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need Always access to notify you when you arrive, even when the app is closed.</string>
Kemudian daftarkan wilayah:
import { BackgroundGeolocation } from '@capgo/background-geolocation';
await BackgroundGeolocation.setupGeofencing({
url: 'https://api.example.com/v1/geofence-events',
headers: { Authorization: 'Bearer <token>' },
notifyOnEntry: true,
notifyOnExit: true,
payload: { userId: 'u-42' },
});
await BackgroundGeolocation.addGeofence({
identifier: 'store-paris-11',
latitude: 48.8606,
longitude: 2.3795,
radius: 150,
payload: { storeId: 'paris-11' },
});
await BackgroundGeolocation.addListener('geofenceTransition', (event) => {
console.log(`${event.transition} ${event.identifier}`, event.payload);
});
await BackgroundGeolocation.addListener('geofenceError', (event) => {
console.error('Geofence error', event.identifier, event.code, event.message);
});
setupGeofencing Minta izin geofencing yang dibutuhkan secara default (requestPermissions berdasarkan default trueberlaku secara default
Kini, mode gagalnya.
1. Anda tidak memiliki otorisasi Selalu.
Pengawasan wilayah di iOS memerlukan otorisasi Selalu. Dengan hanya menggunakan aplikasi, wilayah Anda tidak akan mengirimkan peristiwa ketika aplikasi berada di latar belakang atau tidak berjalan, yang merupakan tujuan utama dari geofence.
Periksa sebelum Anda mendaftarkan wilayah, dan jelaskan permintaan di UI Anda sendiri terlebih dahulu:
const status = await BackgroundGeolocation.checkPermissions();
if (status.backgroundLocation !== 'always' && status.backgroundLocation !== 'granted') {
// Show your own screen explaining the feature, then:
const next = await BackgroundGeolocation.requestPermissions({
permissions: ['backgroundLocation'],
});
if (next.backgroundLocation === 'when_in_use' || next.backgroundLocation === 'denied') {
await BackgroundGeolocation.openSettings();
}
}
Perlu diingat bahwa iOS mungkin tidak menampilkan prompt peningkatan Selalu segera. Pengguna yang memilih “Izinkan Sementara Menggunakan Aplikasi” hanya akan melihat prompt kedua kemudian. Pengguna yang memilih “Izinkan Sekali” mendapatkan hak sementara yang akan direset. Jika geofencing adalah fitur utama, periksa status setiap kali aplikasi dijalankan dan tunjukkan banner yang jelas ketika bukan Selalu.
2. Perangkat sudah berada di dalam wilayah.
Jika Anda menambahkan geofence ketika ponsel sedang berada di dalamnya, iOS tidak akan mengirimkan peristiwa masuk. Tidak ada yang berlalu. Tim sering mengalami masalah ini ketika melakukan tes di meja kerja dengan wilayah di sekitar kantor.
Perbaiki di aplikasi Anda: ketika Anda mendaftarkan wilayah, bandingkan posisi saat ini dengan wilayah dan tangani “sudah berada di dalam” sendiri.
import { Geolocation } from '@capacitor/geolocation';
function distanceMeters(lat1: number, lon1: number, lat2: number, lon2: number) {
const R = 6371000;
const toRad = (d: number) => (d * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
return 2 * R * Math.asin(Math.sqrt(a));
}
const region = { identifier: 'store-paris-11', latitude: 48.8606, longitude: 2.3795, radius: 150 };
await BackgroundGeolocation.addGeofence(region);
const pos = await Geolocation.getCurrentPosition({ enableHighAccuracy: true });
if (distanceMeters(pos.coords.latitude, pos.coords.longitude, region.latitude, region.longitude) < region.radius) {
handleAlreadyInside(region.identifier);
}
declare function handleAlreadyInside(id: string): void;
Untuk menguji peristiwa masuk, berjalan-jalan atau berkendara keluar jauh dari radius, tunggu, lalu kembali.
3. Jarak radius terlalu kecil.
iOS menerima jarak radius kecil, tetapi keandalan menurun cepat di bawah sekitar 100 meter, karena pengawasan wilayah bergantung pada Wi-Fi dan posisi seluler. Wilayah radius 30 meter di sekitar pintu toko mungkin akan mengirimkan peristiwa terlambat, mengirimkan peristiwa setelah pelanggan telah meninggalkan, atau tidak mengirimkan peristiwa sama sekali.
Nilai praktis:
| Kasus penggunaan | Jarak yang disarankan |
|---|---|
| Kedatangan toko atau restoran | 100 hingga 200 m |
| Gedung perkantoran, kampus, gudang | 150 hingga 300 m |
| Zona kecamatan atau kota | 500 m dan di atas |
If you need door level precision, combine a larger geofence with foreground location or a beacon once the user is inside. Capgo also has an __CAPGO_KEEP_0__ juga memiliki untuk kejadian dekat ruang dalam.
untuk keakuratan ruang dalam.
Sebuah aplikasi iOS dapat memantau maksimal 20 wilayah sekaligus. Ketika Anda menambahkan lebih banyak, pendaftaran gagal untuk yang tambahan dan Anda mendapatkan kesalahan pemantauan.
Gunakan getMonitoredGeofences() Untuk melihat apa yang sebenarnya terdaftar, dan simpan set region terdekat yang berubah-ubah:
const { regions } = await BackgroundGeolocation.getMonitoredGeofences();
console.log(`Monitoring ${regions.length} regions`, regions);
Aplikasi patern umum:
- Tetapkan daftar lengkap tempat-tempat di server.
- When the app starts, and when the user moves far (for example on exit of a large “refresh” region around the user), fetch the 19 nearest places.
- refresh
removeAllGeofences()Lalu tambahkan 19 wilayah terdekat plus satu wilayah besar yang berpusat pada pengguna. Keluar dari wilayah besar tersebut adalah tanda untuk memperbarui.
Android memungkinkan hingga 100 geofence per aplikasi, jadi code yang berfungsi di Android mungkin gagal di iOS karena alasan ini saja.
5. Waktu tes terlalu singkat atau terlalu statis
iOS reports transitions only after the device has clearly crossed and stayed on the other side. If you drive through a 150 meter region at 50 km/h, you spend about 20 seconds inside it. That may not be enough.
Saat melakukan pengujian:
- Tunggu di luar selama satu menit, kemudian masuk dan tinggallah setidaknya beberapa menit.
- Test dengan Wi-Fi aktif. Mengaktifkan Wi-Fi membuat pemantauan wilayah menjadi kurang akurat, bahkan jika Anda tidak terhubung ke jaringan apa pun.
- Tidak bergantung pada Simulator untuk waktu. Gunakan Simulator dengan rute GPX di Xcode untuk memeriksa handler Anda, kemudian test di perangkat.
6. Event yang terjadi, tetapi JavaScript Anda tidak berjalan.
Ketika iOS memulai kembali aplikasi Anda di latar belakang untuk event wilayah, plugin native menerima, tetapi WebView Capacitor mungkin tidak dimuat atau mungkin ditangguhkan lagi dengan cepat. geofenceTransition Pengaturan hanya berfungsi ketika WebView masih hidup.
Itulah mengapa setupGeofencing Menerima urlmenerima. Plugin mengirimkan transisi dari native code, termasuk penggabungan payloadsehingga backend Anda mendapatkannya bahkan ketika JavaScript tidak pernah berjalan. Kepala yang disimpan dengan pengaturan masih berfungsi setelah memulai ulang, dan Anda dapat memutar mereka dengan updateHeaders().
Pengiriman berusaha terbaik, dengan tidak ada antrian ulang. Buat endpoint cepat dan idempoten, dan log setiap permintaan selama pengujian.
7. Layanan Lokasi atau Pengaktifan Aplikasi Latar Belakang dimatikan
Periksa hal-hal ini pada perangkat uji:
- Pengaturan, Privasi & Keamanan, Layanan Lokasi diaktifkan.
- Aplikasi Anda diatur untuk selalu aktif.
- Lokasi yang Akurat diaktifkan untuk aplikasi Anda. Tanpa itu, wilayah kecil tidak dapat diandalkan.
- Mode Energi Rendah dimatikan selama tes awal. Ini mengurangi aktivitas latar belakang.
8. Reboot dan pembaruan aplikasi
iOS menjaga wilayah yang diawasi di seluruh peluncuran aplikasi. Setelah restart perangkat, pemantauan akan melanjutkan setelah sistem kembali online, tetapi aplikasi Anda harus masih sinkron ulang wilayahnya pada peluncuran: bandingkan getMonitoredGeofences() dengan apa yang Anda harapkan dan tambahkan kembali wilayah yang hilang. Lakukan hal yang sama setelah pembaruan aplikasi, dan ketika server mengubah daftar tempat.
Pada Android, wilayah geofence dihapus setelah restart dan dalam beberapa situasi lain (lokasi dimatikan, data aplikasi dibersihkan), sehingga perlu mendaftar ulang pada peluncuran. Melakukannya pada kedua platform menjaga logika sederhana.
9. Keluarkan Aplikasi dari Jendela Pemutus
Jika pengguna keluar aplikasi dari jendela pemutus, iOS akan menganggapnya sebagai tanda kuat bahwa pengguna tidak ingin aplikasi berjalan. Perilaku relaunch wilayah setelah keluar aplikasi paksa telah berubah di seluruh versi iOS. Jangan bangun fitur yang hanya berfungsi jika aplikasi diluncurkan kembali setelah keluar aplikasi paksa, dan tesnya pada versi iOS yang digunakan pengguna.
Daftar Periksa Pengembangan
| Periksa | Bagaimana |
|---|---|
| Permission is Always | checkPermissions() mengembalikan always atau granted Bagaimana backgroundLocation |
| Wilayah yang terdaftar | getMonitoredGeofences() menampilkan identifier |
| Wilayah di bawah 20 | Hitung dari getMonitoredGeofences() |
| Jarak ≥ 100 m | Ulas kembali addGeofence menghubungi |
| Tidak sudah berada di dalam | Bandingkan posisi saat ini pada registrasi |
| Error yang dicatat | Dengarkan geofenceError |
| Backend menerima event | Set url in setupGeofencing dan log permintaan |
| dan log permintaan | Keluar dari wilayah sepenuhnya, tunggu, kembali dan tinggal. |
Perbedaan Android yang perlu diperhatikan
If code sama bekerja di Android tapi tidak iOS, batasan wilayah 20 dan syarat selalu aktif adalah alasan biasa. Jika bekerja di iOS tapi tidak Android, periksa apakah Anda telah menambahkan ACCESS_BACKGROUND_LOCATION ke dalam manifest dan atur backgroundLocation: true dalam setupGeofencing. Plugin tidak menambahkan izin tersebut untuk Anda, karena Google Play memerlukan deklarasi untuk lokasi latar belakang.
Pengaturan pengiriman
Kata-kata izin dan konfigurasi native memerlukan build baru. Daftar wilayah, nilai radius, dan teks UI dapat diubah melalui server atau dikirim melalui Capgo pembaruan liveUntuk pemantauan terus-menerus daripada event masuk dan keluar, lihat Mengapa iOS Berhenti Mengupdate Lokasi di Latar BelakangPengaturan pengiriman documentation untuk informasi lengkap API.