Langsung ke konten utama

Mengapa iOS menghentikan update lokasi di background

Kenapa iOS menghentikan background location updates di app Capacitor: suspensi, background modes, otorisasi, auto pause, akurasi, dan cara memperbaiki tiap penyebabnya.

Ilustrasi aplikasi iPhone yang menjalankan tugas latar belakang sambil melacak lokasi

iOS menghentikan pembaruan lokasi latar belakang karena sistem menangguhkan aplikasi Anda, bukan karena Core Location gagal. Kecuali aplikasi mendeklarasikan mode latar belakang lokasi, mengaktifkan pembaruan latar belakang di CLLocationManager, dan memulainya saat masih di latar depan, iOS membekukan proses beberapa detik setelah pengguna keluar, lalu mengantrikan atau membuang data lokasi. Panduan ini merangkum semua penyebab yang kami temui di aplikasi Capacitor, beserta solusinya, dan menunjukkan bagaimana @capgo/background-geolocation menanganinya.

Cara iOS menangani aplikasi di background

Saat pengguna menggeser ke layar beranda atau mengunci ponsel, iOS memberi aplikasi jendela waktu singkat, lalu menangguhkannya. Aplikasi yang ditangguhkan tidak mendapat waktu CPU. Untuk aplikasi Capacitor, ini berarti sisi native dan WebView berhenti berjalan, sehingga callback JavaScript Anda juga berhenti terpanggil.

Apple membuat pengecualian untuk aplikasi yang sedang aktif menggunakan lokasi. Jika aplikasi dikonfigurasi untuk lokasi latar belakang dan memiliki sesi lokasi aktif yang dimulai di latar depan, iOS akan membiarkannya tetap berjalan dan terus mengirimkan pembaruan. Semua di bawah ini membahas cara memenuhi kontrak tersebut, serta kasus saat sistem sengaja melanggarnya.

Penyebab 1: mode background location tidak ada

Tanpa location di UIBackgroundModes, sebanyak apa pun code, pembaruan tidak akan terus mengalir. Tambahkan ke ios/App/App/Info.plist:

<key>UIBackgroundModes</key>
<array>
  <string>location</string>
</array>

Anda juga bisa mengaktifkannya di Xcode di bawah Signing & Capabilities, Background Modes, Location updates. Ini adalah kunci plist, bukan entitlement, jadi tidak perlu mengubah provisioning profile.

Properti native di baliknya adalah allowsBackgroundLocationUpdates. Mengaturnya ke true tanpa background mode di plist, aplikasi akan crash. Plugin Capgo menyetelnya untuk Anda saat Anda mengirim backgroundMessage ke start(), jadi kunci plist harus ada sebelum Anda rilis.

App Review memeriksa apakah background mode tersebut beralasan. Jelaskan di catatan review fitur mana yang menggunakannya, dan pastikan fitur tersebut terlihat oleh reviewer.

Penyebab 2: update dimulai dari background

Aturan Apple: pembaruan latar belakang berlanjut jika dimulai saat aplikasi berada di foreground. Mencoba memulai sesi dari silent push, background fetch, atau BGTaskScheduler task tidak berfungsi untuk pembaruan lokasi standar.

Mulai pelacakan dari aksi pengguna atau saat aplikasi di-resume:

import { App } from '@capacitor/app';
import { BackgroundGeolocation } from '@capgo/background-geolocation';

let tracking = false;

export async function startTracking() {
  if (tracking) return;
  tracking = true;
  await BackgroundGeolocation.start(
    {
      backgroundMessage: 'Recording your route',
      backgroundTitle: 'Route recording',
      requestPermissions: true,
      distanceFilter: 10,
      url: 'https://api.example.com/v1/points',
    },
    (location, error) => {
      if (error) return console.error(error);
      if (location) console.log(location.latitude, location.longitude);
    },
  );
}

// Re-arm when the user comes back, if the session should be active
App.addListener('appStateChange', ({ isActive }) => {
  if (isActive && shouldBeTracking()) startTracking();
});

declare function shouldBeTracking(): boolean;

Penyebab 3: backgroundMessage tidak diteruskan

Ini spesifik untuk plugin Capgo dan merupakan laporan bug yang paling umum. Jika backgroundMessage tidak terdefinisi, plugin akan mengonfigurasi location manager hanya untuk penggunaan foreground: allowsBackgroundLocationUpdates tetap false dan update berhenti saat aplikasi di-suspend. Berikan pesan di kedua platform. Di Android, pesan itu juga menjadi teks notifikasi foreground service.

Penyebab 4: level otorisasi yang salah, atau Allow Once

Banyak developer mengira mereka butuh izin Always untuk tracking di background. Padahal tidak. Apple mendokumentasikan bahwa aplikasi dengan otorisasi When In Use tetap bisa berjalan di background selama layanan lokasi aktif dan background updates diaktifkan.

Always berguna untuk hal lain: menjalankan ulang aplikasi yang sudah terminated. Hanya region monitoring, significant-change location, dan visits yang bisa menjalankan ulang aplikasi, itu pun harus dengan izin Always.

Dua pilihan pengguna ini diam-diam merusak background tracking:

  • Izinkan Sekali. Ini adalah izin When In Use sementara yang kedaluwarsa saat aplikasi tidak lagi digunakan. Sesi berikutnya dimulai dari “not determined” lagi.
  • While Using, lalu prompt Always tidak pernah muncul. Saat Anda meminta izin Always, iOS mungkin menampilkan prompt upgrade nanti, pada waktu yang dipilihnya sendiri, sering kali saat aplikasi tidak sedang di layar.

Cek status sebenarnya sebelum memulai sesi:

import { BackgroundGeolocation } from '@capgo/background-geolocation';

const status = await BackgroundGeolocation.checkPermissions();

if (status.location !== 'granted') {
  await BackgroundGeolocation.requestPermissions({ permissions: ['location'] });
}

if (status.backgroundLocation === 'when_in_use') {
  // Background tracking still works for standard updates.
  // Explain why Always helps if you also rely on geofences.
}

Di iOS, backgroundLocation mengembalikan when_in_use atau granted / always, sehingga Anda bisa menampilkan penjelasan yang tepat tanpa perlu menebak.

Penyebab 5: Core Location menjeda update secara otomatis

CLLocationManager.pausesLocationUpdatesAutomatically defaultnya adalah true. Saat iOS menganggap pengguna tidak bergerak, iOS menjeda pembaruan untuk menghemat baterai. Untuk aplikasi When In Use, jeda ini mengakhiri akses lokasi sampai aplikasi dibuka lagi, dan Core Location tidak melanjutkan sendiri.

Plugin Capgo mengatur pausesLocationUpdatesAutomatically = false di code native-nya, jadi ini sudah ditangani. Jika Anda menulis code native sendiri, atau menggunakan plugin lain, periksa properti ini dulu.

Penyebab 6: perangkat diam dan filter terlalu besar

Dengan distanceFilter dari 50 meter, ponsel yang diletakkan di meja tidak menghasilkan update. Itu terlihat seperti “tracking berhenti” di log Anda, tetapi sebenarnya bekerja sesuai desain.

  • Jika Anda membutuhkan heartbeat saat diam, gunakan nilai kecil atau nol distanceFilter.
  • Gunakan minIntervalMs untuk membatasi seberapa sering native POST dikirim, alih-alih menggunakan filter jarak yang besar.
await BackgroundGeolocation.start(
  {
    backgroundMessage: 'Vehicle tracking active',
    distanceFilter: 0,
    minIntervalMs: 120_000, // at most one native POST every 2 minutes
    url: 'https://api.example.com/v1/vehicle-points',
  },
  () => {},
);

Penyebab 7: Precise Location dimatikan

Sejak iOS 14, pengguna bisa mematikan Precise Location untuk aplikasi Anda. Anda tetap mendapat update, tapi lokasinya hanya perkiraan (beberapa kilometer) dan jauh lebih jarang. Deteksi hal ini di data Anda (nilai accuracy besar) dan jelaskan ke pengguna mengapa lokasi presisi penting untuk fitur Anda. Jika Anda membuat aplikasi pengiriman atau fitness, tunjukkan ini saat onboarding, bukan setelah perjalanan yang buruk.

Penyebab 8: pengguna menutup paksa aplikasi

Jika pengguna menggeser aplikasi di app switcher, iOS akan menghentikan update lokasi standar. Tidak ada plugin yang bisa menjaganya tetap jalan. Ini sering mengejutkan tim yang pindah dari Android, di mana foreground service bisa tetap jalan setelah task dihapus.

Opsi:

  • Beri tahu pengguna agar tidak force quit selama sesi. Sebagian besar aplikasi fleet melakukannya saat onboarding.
  • Tambahkan geofence dengan otorisasi Always di sekitar tempat penting agar iOS bisa meluncurkan ulang aplikasi di background saat masuk atau keluar area.
  • Kirim push notification untuk mengingatkan pengguna membuka kembali aplikasi saat server Anda berhenti menerima titik lokasi selama sesi berlangsung.

Penyebab 9: JavaScript tidak berjalan meski native tetap jalan

Hal yang cukup halus. Native code bisa menerima lokasi saat WebView sedang suspend, atau saat masih aktif tapi tidak memproses timer atau network call dengan cepat. Jika Anda mengirim titik lokasi dengan fetch dari callback, data bisa tiba terlambat atau tidak sama sekali.

Gunakan plugin url opsi plugin. Setiap titik di-POST dari native code dengan JSON yang sama seperti Location type ditambah "source": "native", terlepas dari WebView. Gunakan callback hanya untuk update UI. Pengiriman bersifat best effort tanpa antrean on-disk, jadi jika satu point tidak boleh hilang, simpan juga secara lokal saat callback terpicu dan rekonsiliasi nanti.

Untuk pekerjaan background selain lokasi, baca cara kerja background task di Capacitor dan lihat @capgo/capacitor-background-task.

Penyebab 10: Low Power Mode dan thermal state

Low Power Mode mengurangi aktivitas background di seluruh sistem. Lokasi tetap berfungsi, tetapi hal lain yang bergantung pada sesi Anda (network retries, background refresh) akan melambat. Tes dengan Low Power Mode aktif sebelum merilis aplikasi.

Indikator biru

Saat aplikasi dengan otorisasi When In Use menggunakan lokasi di background, iOS menampilkan indikator biru di status bar. Plugin Capgo mengatur showsBackgroundLocationIndicator ke true untuk sesi background, sesuai dengan ekspektasi pengguna dan apa yang dicari oleh reviewer. Jangan mencoba menyembunyikannya, karena pengguna mempercayainya.

Rencana pengujian yang menangkap bug-bug ini

Testing di Simulator tidak cukup untuk background location. Gunakan iPhone asli dan:

  1. Build konfigurasi release, bukan cuma debug. Debug build yang terpasang di Xcode mendapat perlakuan lifecycle berbeda.
  2. Mulai sesi di foreground, kunci ponsel, lalu jalan atau berkendara selama 20 menit.
  3. Ulangi dengan “Allow Once”, dengan Precise Location mati, dan Low Power Mode aktif.
  4. Cek server logs Anda untuk source: "native" titik, bukan cuma in-app log Anda.
  5. Force quit saat sesi berjalan dan pastikan app Anda menjelaskan apa yang terjadi saat dibuka kembali.

Jika Anda butuh UDID perangkat untuk ad hoc builds, gunakan Pencari UDID iOS didapat dari Safari. Jika Anda tidak punya Mac dengan Xcode 26 untuk build, Build Capgo bisa membuat build iOS yang signed di cloud.

Checklist troubleshooting

Gejala Kemungkinan penyebab Perbaikan
Berhenti beberapa detik setelah dikunci Tidak location background mode atau tidak backgroundMessage Tambahkan key plist dan teruskan backgroundMessage
Crash saat start allowsBackgroundLocationUpdates tanpa background mode Tambah UIBackgroundModes → location
Berfungsi sekali, lalu tidak lagi Pengguna memilih Izinkan Sekali Jelaskan dan minta lagi, atau kirim ke openSettings()
Berhenti saat diparkir Besar distanceFilter Turunkan, gunakan minIntervalMs
Titik berjauhan, akurasi rendah Lokasi Tepat nonaktif Minta pengguna mengaktifkannya
Berhenti setelah di-swipe User menutup aplikasi Wajar di iOS, gunakan geofence untuk relaunch
Native dapat poin, server tidak JavaScript fetch di dalam callback Gunakan url opsi

Rilis perbaikan

Sebagian besar perbaikan ini menyangkut Info.plist atau konfigurasi native, jadi butuh build App Store baru. Bagian JavaScript, seperti penjelasan izin, teks onboarding, dan logika retry, bisa dikirim ke pengguna yang sudah ada via Live updates Capgo setelah native build keluar.

Jika Anda sedang memilih di antara plugin, perbandingan kami antara Transistorsoft dan plugin Capgo gratis membahas trade-off-nya.

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.