Saya mencari cara untuk mendapatkan pembaruan lokasi latar belakang setiap n menit di aplikasi iOS saya. Saya menggunakan iOS 4.3 dan solusinya harus berfungsi untuk iPhone yang tidak dipenjara.
Saya mencoba / mempertimbangkan opsi berikut:
CLLocationManager startUpdatingLocation/startMonitoringSignificantLocationChanges
: Ini berfungsi di latar belakang seperti yang diharapkan, berdasarkan pada properti yang dikonfigurasikan, tetapi tampaknya tidak mungkin untuk memaksanya memperbarui lokasi setiap n menitNSTimer
: Tidak berfungsi saat aplikasi berjalan di latar depan tetapi tampaknya tidak dirancang untuk tugas latar belakang- Pemberitahuan lokal: Pemberitahuan lokal dapat dijadwalkan setiap n menit, tetapi tidak mungkin untuk mengeksekusi beberapa kode untuk mendapatkan lokasi saat ini (tanpa pengguna harus meluncurkan aplikasi melalui pemberitahuan). Pendekatan ini juga tampaknya tidak menjadi pendekatan yang bersih karena ini bukan untuk apa notifikasi harus digunakan.
UIApplication:beginBackgroundTaskWithExpirationHandler
: Sejauh yang saya mengerti, ini harus digunakan untuk menyelesaikan beberapa pekerjaan di latar belakang (juga terbatas waktu) ketika aplikasi dipindahkan ke latar belakang daripada menerapkan proses latar belakang "jangka panjang".
Bagaimana saya bisa menerapkan pembaruan lokasi latar belakang biasa ini?
Jawaban:
Saya menemukan solusi untuk mengimplementasikannya dengan bantuan Forum Pengembang Apple:
location background mode
NSTimer
di latar belakang denganUIApplication:beginBackgroundTaskWithExpirationHandler:
n
ini lebih kecil daripadaUIApplication:backgroundTimeRemaining
itu akan bekerja dengan baik. Ketikan
adalah lebih besar , yanglocation manager
harus diaktifkan (dan dinonaktifkan) lagi sebelum ada waktu yang tersisa untuk menghindari tugas latar belakang dibunuh.Ini berfungsi karena lokasi adalah salah satu dari tiga jenis eksekusi latar belakang yang diizinkan .
Catatan: Saya kehilangan waktu dengan menguji ini di simulator yang tidak berfungsi. Namun, itu berfungsi dengan baik di ponsel saya.
sumber
Pada iOS 8/9/10 untuk membuat pembaruan lokasi latar belakang setiap 5 menit lakukan hal berikut:
Pergi ke Proyek -> Kemampuan -> Mode Latar Belakang -> pilih Pembaruan lokasi
Pergi ke Project -> Info -> tambahkan NSLocationAlwaysUsageDescription kunci dengan nilai kosong (atau opsional teks apa pun)
Untuk membuat lokasi berfungsi ketika aplikasi Anda berada di latar belakang dan mengirim koordinat ke layanan web atau melakukan apa saja dengan mereka setiap 5 menit menerapkannya seperti dalam kode di bawah ini.
Saya tidak menggunakan tugas atau timer latar belakang. Saya telah menguji kode ini dengan perangkat saya dengan iOS 8.1 yang berbaring di meja saya selama beberapa jam dengan aplikasi saya berjalan di latar belakang. Perangkat dikunci dan kode berjalan dengan benar sepanjang waktu.
sumber
if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { [self.locationManager setAllowsBackgroundLocationUpdates:YES]; }
Saya melakukan ini dalam aplikasi yang saya kembangkan. Penghitung waktu tidak berfungsi ketika aplikasi di latar belakang tetapi aplikasi terus menerima pembaruan lokasi. Saya membaca di suatu tempat di dokumentasi (sepertinya saya tidak dapat menemukannya sekarang, saya akan memposting pembaruan ketika saya melakukannya) bahwa suatu metode dapat dipanggil hanya pada loop run aktif ketika aplikasi di latar belakang. Delegasi aplikasi memiliki loop jalankan aktif bahkan dalam bg sehingga Anda tidak perlu membuat sendiri untuk membuat ini berfungsi. [Saya tidak yakin apakah ini penjelasan yang benar, tapi itulah bagaimana saya mengerti dari apa yang saya baca]
Pertama-tama, tambahkan
location
objek untuk kunciUIBackgroundModes
di info aplikasi Anda. Sekarang, yang perlu Anda lakukan adalah memulai pembaruan lokasi di mana saja di aplikasi Anda:Selanjutnya, tulis metode untuk menangani pembaruan lokasi, katakanlah
-(void)didUpdateToLocation:(CLLocation*)location
, dalam delegasi aplikasi. Kemudian menerapkan metodelocationManager:didUpdateLocation:fromLocation
dariCLLocationManagerDelegate
dalam kelas di mana Anda mulai manajer lokasi (karena kita menetapkan lokasi manager delegasi untuk 'diri'). Di dalam metode ini Anda perlu memeriksa apakah interval waktu setelah Anda menangani pembaruan lokasi telah berlalu. Anda dapat melakukan ini dengan menghemat waktu saat ini setiap saat. Jika waktu itu telah lewat, panggil metode UpdateLocation dari delegasi aplikasi Anda:Ini akan memanggil metode Anda setiap 5 menit bahkan ketika aplikasi Anda di latar belakang. Imp: Implementasi ini menguras baterai, jika keakuratan data lokasi Anda tidak kritis yang harus Anda gunakan
[locationManager startMonitoringSignificantLocationChanges]
Sebelum menambahkan ini ke aplikasi Anda, silakan baca Panduan Pemrograman Kesadaran Lokasi
sumber
Sekarang iOS6 adalah cara terbaik untuk memiliki layanan lokasi yang berjalan selamanya ...
Cukup diuji seperti itu:
Saya memulai aplikasi, pergi latar belakang dan bergerak di dalam mobil beberapa menit. Kemudian saya pulang ke rumah selama 1 jam dan mulai bergerak lagi (tanpa membuka aplikasi lagi). Lokasi dimulai lagi. Kemudian berhenti selama dua jam dan mulai lagi. Semuanya baik-baik saja lagi ...
JANGAN LUPA MENGGUNAKAN layanan lokasi baru di iOS6
sumber
Untuk orang lain yang memiliki mimpi buruk, cari tahu yang ini. Saya punya solusi sederhana.
Tambahkan timer dengan menggunakan:
Hanya saja, jangan lupa menambahkan "Daftar aplikasi untuk pembaruan lokasi" di info.plist.
sumber
Inilah yang saya gunakan:
Saya memulai pelacakan di AppDelegate seperti itu:
sumber
Sayangnya, semua asumsi Anda tampaknya benar, dan saya tidak berpikir ada cara untuk melakukan ini. Untuk menghemat masa pakai baterai, layanan lokasi iPhone didasarkan pada pergerakan. Jika ponsel duduk di satu tempat, itu tidak terlihat oleh layanan lokasi.
Hanya
CLLocationManager
akan meneleponlocationManager:didUpdateToLocation:fromLocation:
ketika telepon menerima pembaruan lokasi, yang hanya terjadi jika salah satu dari tiga layanan lokasi (menara seluler, gps, wifi) merasakan perubahan.Beberapa hal lain yang mungkin membantu menginformasikan solusi lebih lanjut:
Memulai & Menghentikan layanan menyebabkan
didUpdateToLocation
metode delegasi dipanggil, tetapinewLocation
mungkin memiliki cap waktu lama.Pemantauan Wilayah mungkin membantu
Saat berjalan di latar belakang, ketahuilah bahwa mungkin sulit untuk mendapatkan dukungan LocationServices "penuh" yang disetujui oleh Apple. Dari apa yang saya lihat, mereka secara khusus dirancang
startMonitoringSignificantLocationChanges
sebagai alternatif daya rendah untuk aplikasi yang membutuhkan dukungan lokasi latar belakang, dan sangat mendorong pengembang untuk menggunakan ini kecuali aplikasi benar-benar membutuhkannya.Semoga berhasil!
UPDATE: Pikiran-pikiran ini mungkin sudah ketinggalan zaman sekarang. Sepertinya orang-orang sukses dengan jawaban @wans, di atas.
sumber
startMonitoringSignificantLocationChanges
tidak akan memberikan pembaruan dalam hal itu.Saya memang menulis aplikasi menggunakan layanan Lokasi, aplikasi harus mengirim lokasi setiap 10-an. Dan itu bekerja dengan sangat baik.
Cukup gunakan metode " allowDeferredLocationUpdatesUntilTraveled: timeout ", mengikuti dokumen Apple.
Apa yang saya lakukan adalah:
Diperlukan: Daftarkan mode latar belakang untuk memperbarui Lokasi.
1. Buat
LocationManger
danstartUpdatingLocation
, denganaccuracy
danfilteredDistance
apa pun yang Anda inginkan:2. Agar aplikasi berjalan selamanya menggunakan
allowDeferredLocationUpdatesUntilTraveled:timeout
metode di latar belakang, Anda harus memulai kembaliupdatingLocation
dengan parameter baru saat aplikasi pindah ke latar belakang, seperti ini:3. Aplikasi mendapat updateLokasi seperti biasa dengan
locationManager:didUpdateLocations:
panggilan balik:4. Tetapi Anda harus menangani data di kemudian
locationManager:didFinishDeferredUpdatesWithError:
panggilan balik untuk tujuan Anda5. CATATAN: Saya pikir kita harus mengatur ulang parameter
LocationManager
setiap kali aplikasi beralih antara mode latar / latar.sumber
pausesLocationUpdatesAutomatically = true
memberitahu manajer lokasi untuk menjeda pembaruan jika tampaknya tidak ada perubahan lokasi ( dokumen Apple ). Lagi pula, saya belum secara eksplisit menguji kasuslocation manager pauses updates
: D.pausesLocationUpdatesAutomatically = true
menyebabkan aplikasi saya berhenti memperbarui lokasi.Ini diperlukan untuk pelacakan lokasi latar belakang sejak iOS 9.
sumber
Saya menggunakan metode xs2bush untuk mendapatkan interval (menggunakan
timeIntervalSinceDate
) dan diperluas sedikit. Saya ingin memastikan bahwa saya mendapatkan akurasi yang diperlukan yang saya butuhkan dan juga bahwa saya tidak kehabisan baterai dengan menjaga radio gps lebih dari yang diperlukan.Saya menjaga lokasi berjalan terus menerus dengan pengaturan berikut:
ini adalah daya baterai yang relatif rendah. Ketika saya siap untuk mendapatkan pembacaan lokasi berkala berikutnya, saya pertama-tama memeriksa untuk melihat apakah lokasi itu dalam akurasi yang saya inginkan, jika ya, saya kemudian menggunakan lokasi. Jika tidak, maka saya meningkatkan akurasi dengan ini:
dapatkan lokasi saya dan kemudian setelah saya memiliki lokasi saya mengembalikan keakuratan kembali untuk meminimalkan pembuangan baterai. Saya telah menulis sampel yang berfungsi penuh dan juga saya telah menulis sumber untuk kode sisi server untuk mengumpulkan data lokasi, menyimpannya ke database dan memungkinkan pengguna untuk melihat data gps secara real time atau mengambil dan melihat rute yang sebelumnya disimpan. Saya punya klien untuk iOS, android, windows phone dan java saya. Semua klien ditulis secara asli dan mereka semua bekerja dengan baik di latar belakang. Proyek ini berlisensi MIT.
Proyek iOS ditargetkan untuk iOS 6 menggunakan SDK dasar iOS 7. Anda bisa mendapatkan kode di sini .
Silakan ajukan masalah pada github jika Anda melihat ada masalah dengannya. Terima kasih.
sumber
Tampaknya stopUpdatingLocation adalah yang memicu timer pengawas latar belakang, jadi saya menggantinya di didUpdateLocation dengan:
yang tampaknya secara efektif mematikan GPS. Selektor untuk latar belakang NSTimer kemudian menjadi:
Yang saya lakukan adalah mengubah akurasi secara berkala untuk mendapatkan koordinat akurasi tinggi setiap beberapa menit dan karena locationManager belum dihentikan, backgroundTimeRemaining tetap pada nilai maksimumnya. Ini mengurangi konsumsi baterai dari ~ 10% per jam (dengan kCLLocationAccuracyBest konstan di latar belakang) hingga ~ 2% per jam di perangkat saya
sumber
Ada cocoapod APScheduledLocationManager yang memungkinkan untuk mendapatkan pembaruan lokasi latar belakang setiap n detik dengan akurasi lokasi yang diinginkan.
Repositori juga berisi contoh aplikasi yang ditulis dalam Swift 3.
sumber
Di iOS 9 dan watchOS 2.0 ada metode baru di CLLocationManager yang memungkinkan Anda meminta lokasi saat ini: CLLocationManager: requestLocation (). Ini selesai segera dan kemudian mengembalikan lokasi ke delegasi CLLocationManager.
Anda dapat menggunakan NSTimer untuk meminta lokasi setiap menit dengan metode ini sekarang dan tidak harus bekerja dengan startUpdatingLocation dan menghentikan metodeUpUpdatingLocation.
Namun jika Anda ingin mengambil lokasi berdasarkan perubahan X meter dari lokasi terakhir, cukup atur properti distanceFilter dari CLLocationManger dan ke X panggil startUpdatingLocation ().
sumber
Terlampir adalah solusi Swift yang berbasis di:
Tentukan
App registers for location updates
dalam info.plistJaga agar pengelola Lokasi tetap berjalan sepanjang waktu
Beralih di
kCLLocationAccuracy
antaraBestForNavigation
(selama 5 detik untuk mendapatkan lokasi) danThreeKilometers
selama sisa periode menunggu untuk menghindari drainase bateraiContoh ini memperbarui lokasi setiap 1 menit di Latar Depan dan setiap 15 menit di Latar Belakang.
Contoh ini berfungsi dengan baik dengan Xcode 6 Beta 6, berjalan di perangkat iOS 7.
Di App Delegate (mapView adalah Opsional menunjuk ke mapView Controller)
Di mapView (locationManager menunjuk ke objek di AppDelegate)
sumber