Langsung ke konten utama

Mengapa Geofence Tidak Terpicu di iOS

Geofence tidak terpicu di iOS pada aplikasi Capacitor Anda? Pelajari cara kerja region monitoring, izin, aturan radius dan limit, serta cara debug tiap kasus.

Peta dengan batas lokasi yang mengilustrasikan geofencing di aplikasi iOS Capacitor

Saat geofence tidak terpicu di iOS, penyebabnya hampir selalu ada di daftar singkat ini: aplikasi tidak punya izin Always, perangkat sudah berada di dalam region saat Anda menambahkannya, radius terlalu kecil untuk dideteksi iOS, aplikasi mencapai batas 20 region, atau pengujiannya tidak menunggu cukup lama. Geofencing iOS bekerja dengan baik, tetapi melaporkan crossing sesuai jadwalnya sendiri. Panduan ini menjelaskan bagaimana region monitoring menentukan kapan harus dipicu, dan cara men-debug aplikasi Capacitor menggunakan @capgo/background-geolocation, yang mencakup native geofencing di iOS dan Android.

Cara kerja region monitoring di iOS

Di iOS, geofence adalah CLCircularRegion objek yang didaftarkan ke Core Location. Setelah didaftarkan, sistem operasi yang memantaunya, bukan aplikasi Anda. Aplikasi Anda bisa dalam keadaan suspended atau tidak berjalan, dan iOS tetap melacak region tersebut dengan kombinasi menara seluler, Wi-Fi, dan GPS untuk menjaga penggunaan baterai tetap rendah.

Ketika iOS memutuskan bahwa perangkat telah melewati batas, ia mengirimkan event enter atau exit ke aplikasi, meluncurkannya di background jika diperlukan dan diizinkan. Beberapa aturan mengontrol keputusan tersebut:

  • iOS tidak melaporkan crossing saat perangkat menyentuh batas. Panduan Apple menyatakan bahwa perangkat harus melewati batas, bergerak minimal jarak tertentu melewati batas, dan tetap di sana selama setidaknya sekitar 20 detik sebelum event dikirimkan. Ini menghindari pemicuan akibat jitter GPS.
  • Akurasi lokasi untuk pemantauan wilayah bergantung pada radio yang tersedia di sekitar. Di kota dengan Wi-Fi padat, prosesnya bisa cepat. Di jalan pedesaan, bisa memakan waktu beberapa menit.
  • Event hanya untuk transisi. Berada di dalam wilayah saat pemantauan dimulai tidak dihitung sebagai entry.

Siapkan geofencing di aplikasi Capacitor

Instal plugin dan konfigurasikan 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>

Lalu 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 meminta izin yang dibutuhkan geofencing secara default (requestPermissions defaultnya adalah true). Di iOS, ini berarti Always.

Sekarang, mode kegagalan.

1. Anda tidak memiliki otorisasi Always

Pemantauan wilayah di iOS membutuhkan otorisasi Always. Dengan While Using App saja, wilayah Anda tidak akan mengirim event saat aplikasi berada di background atau tidak berjalan, padahal itulah tujuan utama geofence.

Periksa sebelum mendaftarkan wilayah, dan jelaskan permintaan tersebut di UI Anda 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();
  }
}

Perhatikan bahwa iOS mungkin tidak langsung menampilkan prompt upgrade Always. Pengguna yang memilih “Allow While Using App” mungkin baru melihat prompt kedua nanti. Pengguna yang memilih “Allow Once” mendapat izin sementara yang akan direset. Jika geofencing adalah fitur inti, periksa statusnya setiap kali aplikasi dimulai dan tampilkan banner yang jelas jika statusnya bukan Always.

2. Perangkat sudah berada di dalam region

Jika Anda menambahkan geofence saat ponsel berada di dalamnya, iOS tidak mengirim event enter. Tidak ada yang melintasi batas. Tim sering menemui masalah ini saat menguji di meja kerja dengan region di sekitar kantor.

Perbaiki di aplikasi Anda: saat mendaftarkan region, bandingkan posisi saat ini dengan region dan tangani kondisi “sudah 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 event enter, berjalan atau berkendara keluar jauh melewati radius, tunggu, lalu kembali.

3. Radius terlalu kecil

iOS menerima radius kecil, tetapi keandalan turun drastis di bawah sekitar 100 meter, karena region monitoring bergantung pada penentuan posisi Wi-Fi dan seluler. Region 30 meter di sekitar pintu toko mungkin memicu terlambat, memicu setelah pelanggan pergi, atau tidak memicu sama sekali.

Nilai praktis:

Kasus penggunaan Radius yang disarankan
Kedatangan di toko atau restoran 100 hingga 200 m
Kantor, kampus, gudang 150 hingga 300 m
Lingkungan atau zona kota 500 m ke atas

Jika butuh presisi hingga level pintu, gabungkan geofence yang lebih besar dengan foreground location atau beacon setelah pengguna berada di dalam. Capgo juga punya plugin iBeacon untuk proximity indoor.

4. Anda mencapai batas 20 region

Aplikasi iOS hanya bisa memantau maksimal 20 region sekaligus. Saat Anda menambahkan lebih banyak, registrasi untuk region tambahan akan gagal dan Anda mendapat error monitoring.

Gunakan getMonitoredGeofences() untuk melihat apa yang benar-benar terdaftar, dan mempertahankan set region terdekat yang terus diperbarui:

const { regions } = await BackgroundGeolocation.getMonitoredGeofences();
console.log(`Monitoring ${regions.length} regions`, regions);

Pola yang umum digunakan:

  1. Simpan daftar lengkap lokasi Anda di server.
  2. Saat aplikasi dimulai, dan saat user berpindah jauh (misalnya saat keluar dari region “refresh” besar di sekitar user), ambil 19 lokasi terdekat.
  3. Panggil removeAllGeofences(), lalu tambahkan 19 lokasi terdekat plus satu region besar yang berpusat pada user. Keluar dari region besar tersebut adalah sinyal untuk refresh.

Android mengizinkan hingga 100 geofence per aplikasi, jadi code yang berjalan di Android bisa gagal di iOS hanya karena alasan ini.

5. Pengujian terlalu singkat atau terlalu statis

iOS melaporkan transisi hanya setelah perangkat benar-benar melewati dan menetap di sisi lain. Jika Anda melewati region 150 meter dengan kecepatan 50 km/jam, Anda hanya berada di dalamnya sekitar 20 detik. Itu mungkin tidak cukup.

Saat melakukan pengujian:

  • Tetap di luar selama satu menit, lalu masuk dan tetap di dalam minimal dua menit.
  • Tes dengan Wi-Fi aktif. Mematikan Wi-Fi membuat region monitoring jauh lebih tidak akurat, walaupun Anda tidak terhubung ke jaringan apa pun.
  • Jangan mengandalkan Simulator untuk soal timing. Gunakan dengan GPX route di Xcode untuk mengecek handler Anda, lalu tes di perangkat.

6. Event terpicu, tapi JavaScript Anda tidak berjalan

Saat iOS menjalankan ulang aplikasi Anda di background untuk sebuah region event, plugin native menerimanya, tetapi Capacitor WebView mungkin belum dimuat atau bisa ditangguhkan lagi dengan cepat. geofenceTransition listener hanya terpicu selama WebView masih hidup.

Itulah sebabnya setupGeofencing menerima sebuah url. Plugin mengirim POST transisi dari native code, termasuk header gabungan payload, sehingga backend Anda tetap menerimanya meskipun JavaScript tidak pernah berjalan. Header disimpan bersama setup sehingga tetap berfungsi setelah relaunch, dan Anda bisa merotasinya dengan updateHeaders().

Pengiriman bersifat best effort, tanpa antrean retry. Buat endpoint tetap cepat dan idempotent, serta log setiap request selama pengujian.

7. Location Services atau Background App Refresh nonaktif

Periksa ini di perangkat uji:

  • Settings, Privacy &amp; Security, Location Services sudah aktif.
  • Aplikasi Anda diatur ke Always.
  • Precise Location aktif untuk aplikasi Anda. Tanpa ini, region kecil tidak bisa diandalkan.
  • Low Power Mode nonaktif selama pengujian pertama Anda. Mode ini mengurangi aktivitas background.

8. Reboot dan pembaruan aplikasi

iOS mempertahankan region yang dipantau di antara peluncuran aplikasi. Setelah perangkat di-restart, monitoring berlanjut begitu sistem menyala kembali, tetapi aplikasi Anda tetap harus re-sync region saat peluncuran: bandingkan getMonitoredGeofences() dengan yang Anda harapkan dan tambahkan kembali yang hilang. Lakukan hal yang sama setelah pembaruan aplikasi, dan setiap kali server mengubah daftar lokasi.

Di Android, geofence dihapus setelah reboot dan dalam beberapa situasi lain (lokasi dimatikan, data aplikasi dihapus), jadi registrasi ulang saat peluncuran memang wajib di sana. Melakukannya di kedua platform membuat logika lebih sederhana.

9. Paksa keluar

Jika pengguna melakukan force quit aplikasi dari app switcher, iOS menganggapnya sebagai sinyal kuat bahwa pengguna tidak ingin aplikasi berjalan. Perilaku relaunch region setelah force quit berubah seiring versi iOS. Jangan membangun fitur yang hanya berfungsi jika aplikasi di-relaunch setelah force quit, dan uji pada versi iOS yang dipakai pengguna Anda.

Checklist debugging

Periksa Bagaimana
Izinnya Always checkPermissions() mengembalikan always atau granted untuk backgroundLocation
Region terdaftar getMonitoredGeofences() mencantumkan identifier
Di bawah 20 region Hitung dari getMonitoredGeofences()
Radius ≥ 100 m Tinjau addGeofence panggilan
Belum berada di dalam Bandingkan posisi saat ini saat registrasi
Error dicatat di log Dengarkan geofenceError
Backend menerima event Atur url di setupGeofencing dan catat request
Tes pergerakan nyata Keluar sepenuhnya dari region, tunggu, kembali dan menetap

Perbedaan Android yang perlu diperhatikan

Jika code yang sama berfungsi di Android tetapi tidak di iOS, batas 20 region dan persyaratan Always biasanya menjadi penyebabnya. Jika berfungsi di iOS tetapi tidak di Android, pastikan Anda sudah menambahkan ACCESS_BACKGROUND_LOCATION ke manifest Anda dan mengatur backgroundLocation: true di setupGeofencing. Plugin tidak menambahkan izin tersebut untuk Anda, karena Google Play memerlukan deklarasi untuk lokasi latar belakang.

Merilis perubahan

String izin dan konfigurasi native memerlukan build baru. Daftar region, nilai radius, dan teks UI bisa diubah di server atau dirilis melalui Live updates Capgo. Untuk pelacakan berkelanjutan alih-alih event masuk dan keluar, lihat mengapa iOS menghentikan pembaruan lokasi latar belakang, dan plugin dokumentasi untuk API selengkapnya.

Live updates untuk aplikasi Capacitor

Saat bug web-layer sudah live, kirim perbaikannya lewat Capgo alih-alih menunggu berhari-hari untuk persetujuan app store. Pengguna mendapat update di background, sementara perubahan native tetap mengikuti jalur review normal.

Terbaru dari Blog kami

Capgo memberikan insight terbaik yang Anda butuhkan untuk membuat aplikasi mobile yang benar-benar profesional.