आवधिक iOS पृष्ठभूमि स्थान अपडेट


91

मैं एक एप्लिकेशन लिख रहा हूं जिसके लिए उच्च सटीकता और कम आवृत्ति के साथ पृष्ठभूमि स्थान अपडेट की आवश्यकता है । समाधान एक पृष्ठभूमि NSTimer कार्य लगता है जो स्थान प्रबंधक के अपडेट को शुरू करता है, जो फिर तुरंत बंद हो जाता है। यह प्रश्न पहले पूछा गया है:

मुझे अपने iOS एप्लिकेशन में हर n मिनट में बैकग्राउंड लोकेशन अपडेट कैसे मिलेगा?

ऐप के बैकग्राउंड में जाने के बाद हर n मिनट में यूजर की लोकेशन मिलना

आईओएस नहीं विशिष्ट पृष्ठभूमि स्थान ट्रैकिंग टाइमर समस्या

"स्थान" पृष्ठभूमि मोड के साथ iOS लंबे समय तक चलने वाला बैकग्राउंड टाइमर

लोकेशन ट्रैकिंग के आधार पर iOS फुलटाइम बैकग्राउंड-सर्विस

लेकिन मुझे अभी तक काम करने का एक न्यूनतम उदाहरण नहीं मिला है । उपर्युक्त स्वीकृत उत्तरों के प्रत्येक क्रमांकन की कोशिश करने के बाद, मैंने एक प्रारंभिक बिंदु को एक साथ रखा। पृष्ठभूमि दर्ज करना:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"ending background task");
        [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
        self.bgTask = UIBackgroundTaskInvalid;
    }];


    self.timer = [NSTimer scheduledTimerWithTimeInterval:60
                                                  target:self.locationManager
                                                selector:@selector(startUpdatingLocation)
                                                userInfo:nil
                                                 repeats:YES];
}

और प्रतिनिधि विधि:

- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation {

    NSLog(@"%@", newLocation);

    NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
    [self.locationManager stopUpdatingLocation];

}

वर्तमान व्यवहार यह है कि backgroundTimeRemaining180 सेकंड से शून्य तक (स्थान लॉग करते समय), और फिर समाप्ति हैंडलर निष्पादित होता है और आगे कोई स्थान अपडेट उत्पन्न नहीं होता है। मैं अनिश्चित काल में पृष्ठभूमि में आवधिक स्थान अपडेट प्राप्त करने के लिए उपरोक्त कोड को कैसे संशोधित करूं ?

अद्यतन : मैं iOS 7 को लक्षित कर रहा हूं और कुछ सबूत प्रतीत होते हैं कि पृष्ठभूमि के कार्य अलग-अलग व्यवहार करते हैं:

पृष्ठभूमि कार्य से iOS 7 में स्थान प्रबंधक प्रारंभ करें


आप उल्लेख नहीं करते हैं कि आप किस संस्करण का लक्ष्य बना रहे हैं। iOS 7 (उदाहरण के लिए) में पूर्ववर्ती की तुलना में एक अलग मल्टीटास्किंग सिस्टम है।
जेसन व्हाइटहॉर्न

@JasonWhitehorn अच्छा बिंदु। मैंने सवाल अपडेट किया है।
pcoving

2
@ pcoving: क्या ऐप या मारे जाने पर भी आपका समाधान काम करेगा?
नीरव

जवाबों:


62

ऐसा लगता है कि stopUpdatingLocationपृष्ठभूमि प्रहरी टाइमर को ट्रिगर करता है, इसलिए मैंने इसे इसके didUpdateLocationसाथ बदल दिया :

[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
[self.locationManager setDistanceFilter:99999];

जो जीपीएस को प्रभावी ढंग से बिजली देने के लिए प्रकट होता है। पृष्ठभूमि के लिए चयनकर्ता NSTimerतब बन जाता है:

- (void) changeAccuracy {
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}

मैं जो कुछ भी कर रहा हूं वह हर कुछ मिनटों में उच्च सटीकता प्राप्त करने के लिए समय-समय पर सटीकता से टॉगल करता है और क्योंकि locationManagerरोका नहीं गया backgroundTimeRemainingहै, इसके अधिकतम मूल्य पर रहता है। इससे kCLLocationAccuracyBestमेरी डिवाइस पर बैटरी की खपत ~ 10% प्रति घंटा ( पृष्ठभूमि में स्थिर ) से ~ 2% प्रति घंटे कम हो गई।


4
क्या आप अपने प्रश्न को पूर्ण कार्य उदाहरण के साथ अपडेट कर सकते हैं? कुछ इस तरह: "अद्यतन: मैं समझ से बाहर है। यहाँ मेरा समाधान है ..."
smholloway

@Virussmca मैं एक पिछले उत्तर पर लौट आया जो समान प्रदर्शन के साथ बहुत अधिक मजबूत है। स्थान अद्यतनों को रोकना पूरी तरह से एक दौड़ की स्थिति (या कुछ अन्य गैर-नियतात्मक परिदृश्य) को ट्रिगर करने के लिए लगता है।
pcoving

यह तरीका काम नहीं करेगा जैसा कि आप उम्मीद कर रहे हैं: 1) डिस्टिल्टर संपत्ति के मूल्य में वृद्धि से बैटरी की बचत नहीं होती है क्योंकि जीपीएस को अभी भी आपके स्थान का पता लगाना है। 2) iOS 7 में बैकग्राउंड टाइम नॉन - कंटेस्टेंट है। 3) आप महत्वपूर्ण क्रमानुसार सेवाओं का ध्यान रख सकते हैं। 4) IOS 7 में अपने soution के अलावा आप UIBackgroundModes शुरू नहीं कर सकते हैं - पृष्ठभूमि से स्थान ...
16:

2
@aMother 1) मुझे एहसास है कि दूरी फ़िल्टर को बढ़ाना (और कॉलबैक को संसाधित नहीं करना) ज्यादा बैटरी नहीं बचाता है। हालाँकि, setDesiredAccuracy करता है! यह सेल टॉवर सूचना पर वापस आता है जो मूल रूप से मुफ्त में आता है। 2) गैर-सन्निहित? 3) मैंने बोल्ड में, निर्दिष्ट किया है कि मुझे उच्च सटीकता की आवश्यकता है। महत्वपूर्ण स्थान परिवर्तन इसे प्रदान नहीं करते हैं। 4) स्थान सेवाएं पृष्ठभूमि से शुरू / बंद नहीं की जा रही हैं।
4:00

2
मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन इस ट्रिक का उपयोग करने वाले मेरे एप्लिकेशन के उपयोगकर्ताओं ने iOS9 में अपग्रेड करने के बाद से बैटरी के उपयोग में उल्लेखनीय वृद्धि देखी है। मैंने अभी तक जांच नहीं की है, लेकिन मुझे लगता है कि यह 'चाल' अब और काम नहीं कर सकती है?
गैरी राइट

45

मैंने स्थान सेवाओं का उपयोग करके एक ऐप लिखा था, ऐप को प्रत्येक 10s पर स्थान भेजना होगा। और इसने बहुत अच्छा काम किया।

बस Apple के डॉक्स के बाद " allowDeferredLocationUpdatesUntilTraveled: टाइमआउट " विधि का उपयोग करें ।

चरण इस प्रकार हैं:

आवश्यक: अद्यतन स्थान के लिए पृष्ठभूमि मोड पंजीकृत करें।

1. जो भी आप चाहते हैं, सटीकता और फ़िल्टर किए गए स्थान के साथ, स्थानमंजर और startUpdatingLocation बनाएँ:

-(void) initLocationManager    
{
    // Create the manager object
    self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    _locationManager.delegate = self;
    // This is the most important property to set for the manager. It ultimately determines how the manager will
    // attempt to acquire location and thus, the amount of power that will be consumed.
    _locationManager.desiredAccuracy = 45;
    _locationManager.distanceFilter = 100;
    // Once configured, the location manager must be "started".
    [_locationManager startUpdatingLocation];
}

2. एप्लिकेशन को हमेशा के लिए "allowDeferredLocationUpdatesUntilTraveled: टाइमआउट" पद्धति का उपयोग करके चालू रखने के लिए, आपको ऐप को पृष्ठभूमि पर ले जाते समय नए पैरामीटर के साथ अद्यतन करना शुरू करना होगा, जैसे:

- (void)applicationWillResignActive:(UIApplication *)application {
     _isBackgroundMode = YES;

    [_locationManager stopUpdatingLocation];
    [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [_locationManager setDistanceFilter:kCLDistanceFilterNone];
    _locationManager.pausesLocationUpdatesAutomatically = NO;
    _locationManager.activityType = CLActivityTypeAutomotiveNavigation;
    [_locationManager startUpdatingLocation];
 }

3. ऐप को "लोकल मैनेजर: didUpdateLocations:" कॉलबैक के साथ सामान्य रूप से अपडेट किया जाता है:

-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//  store data
    CLLocation *newLocation = [locations lastObject];
    self.userLocation = newLocation;

   //tell the centralManager that you want to deferred this updatedLocation
    if (_isBackgroundMode && !_deferringUpdates)
    {
        _deferringUpdates = YES;
        [self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
    }
}

4. लेकिन आपको उस डेटा को "लोकेशन मेनेजर: डिफिनिशडिफ्रेडरेड यूपीडेट्सविश्राम": अपने उद्देश्य के लिए कॉलबैक में संभालना चाहिए।

- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {

     _deferringUpdates = NO;

     //do something 
}

5. नोट: मुझे लगता है कि हमें बैकग्राउंड / फ़ोरग्राउंड मोड के बीच हर बार ऐप स्विच करने के लिए लोकेशन मैनेजर के मापदंडों को रीसेट करना चाहिए।


यह बहुत अच्छा काम करता है और मुझे लगता है कि यह पिछले साल WWDC में उल्लिखित तरीका है !! पोस्ट के लिए धन्यवाद
prasad1250

@ samthui7 इस काम के लिए धन्यवाद, लेकिन मुझे समाप्ति के बाद भी स्थान प्राप्त करने की आवश्यकता है। यह कैसे हो सकता है।??
मोहित तोमर

@ samthui7 .. कृपया इस कतार को देखें ... stackoverflow.com/questions/37338466/…
सूरज सुकले

2
@ उमर: मैंने iOS 10 बीटा पर भी जांच की, यह अभी भी काम करता है। ध्यान दें कि हमें startUpdatingLocation से पहले कुछ कोड जोड़ने की आवश्यकता है: allowsBackgroundLocationUpdates = YESऔर requestAlwaysAuthorizationया requestWhenInUseAuthorization। जैसे: `CLLocationManager * locationManager = [[CLLocationManager आबंटित] init]; locationManager.delegate = self; locationManager.allowsBackgroundLocationUpdates = YES; [स्थान प्रबंधक अनुरोधअभिलेखीकरण]; [LocationManager startUpdatingLocation]; `
samthui7

1
@ नीरव नहीं, मुझे नहीं लगता कि Apple हमें ऐसा करने दे सकता है, जहाँ तक मुझे पता है।
samthui7

38
  1. यदि आपके पास चाबी के UIBackgroundModesसाथ अपनी मुट्ठी में है locationतो आपको beginBackgroundTaskWithExpirationHandlerविधि का उपयोग करने की आवश्यकता नहीं है । वह बेमानी है। इसके अलावा, आप इसे गलत तरीके से उपयोग कर रहे हैं ( यहां देखें ) लेकिन यह आपकी लूट के सेट होने के बाद से लूट है।

  2. साथ UIBackgroundModes locationplist में एप्लिकेशन अनिश्चित काल के लिए केवल जब तक पृष्ठभूमि में चलाने के लिए जारी रहेगा CLLocationMangerचल रहा है। अगर आप stopUpdatingLocationबैकग्राउंड में कॉल करते हैं तो ऐप बंद हो जाएगा और फिर से शुरू नहीं होगा।

    हो सकता है कि आप कॉल करने beginBackgroundTaskWithExpirationHandlerसे पहले कॉल कर सकते थे stopUpdatingLocationऔर फिर कॉल करने के बाद startUpdatingLocationआप कॉल कर सकते थे endBackgroundTaskकि जीपीएस बंद रहने के दौरान इसे बैकग्राउंड रखा जाए, लेकिन मैंने कभी कोशिश नहीं की है - यह सिर्फ एक विचार है।

    एक अन्य विकल्प (जो मैंने कोशिश नहीं की है) पृष्ठभूमि में रहते हुए स्थान प्रबंधक को चालू रखने के लिए है, लेकिन एक बार जब आप एक सटीक स्थान प्राप्त कर लेते हैं तो desiredAccuracyसंपत्ति को 1000 मी या उससे अधिक बदल देते हैं ताकि जीपीएस चिप को बंद कर दिया जा सके (बैटरी बचाने के लिए)। फिर 10 मिनट बाद जब आपको किसी अन्य स्थान अपडेट की आवश्यकता होती है, desiredAccuracyतो जीपीएस को चालू करने के लिए 100 मीटर पर वापस जाएं, जब तक कि आपको एक सटीक स्थान प्राप्त न हो, तब तक दोहराएं।

  3. जब आप startUpdatingLocationलोकेशन मैनेजर को कॉल करते हैं तो आपको पोजिशन लेने के लिए समय देना चाहिए। आपको तुरंत फोन नहीं करना चाहिए stopUpdatingLocation। हम इसे अधिकतम 10 सेकंड तक चलने देते हैं या जब तक हमें एक गैर-कैश्ड उच्च सटीकता वाला स्थान नहीं मिल जाता है।

  4. आपको कैश्ड स्थानों को फ़िल्टर करने की आवश्यकता है और यह सुनिश्चित करने के लिए कि आपको यह सुनिश्चित करने के लिए कि यह आपकी न्यूनतम आवश्यक सटीकता को पूरा करती है ( यहाँ देखें )। आपको मिलने वाला पहला अपडेट 10 मिनट या 10 दिन पुराना हो सकता है। आपको प्राप्त होने वाली पहली सटीकता 3000 मी हो सकती है।

  5. इसके बजाय महत्वपूर्ण स्थान परिवर्तन API का उपयोग करने पर विचार करें। एक बार जब आप महत्वपूर्ण परिवर्तन सूचना प्राप्त करते हैं, तो आप CLLocationManagerकुछ सेकंड के लिए उच्च सटीकता की स्थिति प्राप्त कर सकते हैं। मुझे यकीन नहीं है, मैंने कभी भी महत्वपूर्ण स्थान परिवर्तन सेवाओं का उपयोग नहीं किया है।


Apple CoreLocationसंदर्भ beginBackgroundTaskWithExpirationHandlerपृष्ठभूमि में डेटा को संसाधित करते समय उपयोग करने की अनुशंसा करता है : "यदि किसी iOS ऐप को स्थान डेटा को संसाधित करने के लिए अधिक समय की आवश्यकता होती है, तो यह startBackgroundTaskWithName: expirationHandler: UIApplication class की विधि का उपयोग करके अधिक पृष्ठभूमि निष्पादन समय का अनुरोध कर सकता है।" - developer.apple.com/library/ios/documentation/UserExperience/…
eliocs

4
जोड़ना मत भूलना _locationManager.allowsBackgroundLocationUpdates = YES; iOS9 + के लिए, अन्यथा ऐप 180 सेकंड के बाद सो जाएगा
kolyancz

@kolyancz मैंने अभी iPhone 6+ के लिए iOS 10.1.1 पर कोशिश की थी। नींद आने और ट्रिगर होने में लगभग ~ 17 मिनट लग गए locationManagerDidPauseLocationUpdates। मैंने उस व्यवहार को 10 बार सत्यापित किया!
हनी

मैं वास्तव में नहीं मिलता है कि आप यह क्यों कह रहे हैं कि यह मूक है और फिर आप कह रहे हैं कि आपको इसे एक बैकग्राउंड के अंदर लपेटना चाहिए ...
हनी

9

जब यह स्थान सेवा शुरू करने और पृष्ठभूमि कार्य को रोकने का समय है, तो पृष्ठभूमि कार्य को देरी के साथ रोका जाना चाहिए (1 सेकंड पर्याप्त होना चाहिए)। अन्यथा स्थान सेवा अभ्यस्त प्रारंभ। इसके अलावा स्थान सेवा कुछ सेकंड के लिए छोड़ दी जानी चाहिए (उदाहरण के लिए 3 सेकंड)।

एक कोकोपोड APScheduledLocationManager है जो वांछित स्थान सटीकता के साथ हर n सेकंड में पृष्ठभूमि स्थान अपडेट प्राप्त करने की अनुमति देता है ।

let manager = APScheduledLocationManager(delegate: self)
manager.startUpdatingLocation(interval: 170, acceptableLocationAccuracy: 100)

रिपॉजिटरी में स्विफ्ट 3 में लिखा एक उदाहरण ऐप भी है।


1

startMonitoringSignificantLocationChanges:API के साथ इसे आज़माने के बारे में कैसे ? यह निश्चित रूप से कम आवृत्ति के साथ आग लगाता है और सटीकता काफी अच्छी है। इसके अतिरिक्त अन्य locationManagerएपीआई के उपयोग की तुलना में इसके बहुत अधिक फायदे हैं ।

इस लिंक के बारे में इस लिंक पर पहले ही बहुत चर्चा की जा चुकी है


1
मैंने इस दृष्टिकोण की कोशिश की है। यह सटीकता की आवश्यकता का उल्लंघन करता है - डॉक्स से : This interface delivers new events only when it detects changes to the device’s associated cell towers
पीसीओइंग

1

आप अपने आवेदन में स्थान अद्यतन मोड को जोड़ने की जरूरत है आप में निम्नलिखित कुंजी जोड़कर। info.plist।

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

didUpdateToLocationविधि को बुलाया जाएगा (तब भी जब आपका ऐप पृष्ठभूमि में हो)। आप इस विधि कॉल के आधार पर कोई भी कार्य कर सकते हैं


स्थान अद्यतन मोड पहले से ही info.plist में है। जैसा कि मैंने उल्लेख किया है, मुझे 180 सेकंड की पृष्ठभूमि के समय तक अपडेट मिल रहा है।
पीसीओविंग

0

IOS 8 के बाद उनके द्वारा कोरलोकेशन फ्रेमवर्क से संबंधित पृष्ठभूमि में बदलाव और ऐप्पल द्वारा किए गए अपडेशन में कई बदलाव किए गए हैं।

1) ऐप्पल एप्लिकेशन में स्थान अपडेट लाने के लिए ऑल्टरऑउटहोरीकरण अनुरोध का परिचय देता है।

2) Apple ने iOS में बैकग्राउंड से लोकेशन लाने के लिए BackgroundLocationupdates की शुरुआत की।

पृष्ठभूमि में स्थान प्राप्त करने के लिए आपको Xcode की क्षमताओं में स्थान अपडेट सक्षम करना होगा।

//
//  ViewController.swift
//  DemoStackLocation
//
//  Created by iOS Test User on 02/01/18.
//  Copyright © 2018 iOS Test User. All rights reserved.
//

import UIKit
import CoreLocation

class ViewController: UIViewController {

    var locationManager: CLLocationManager = CLLocationManager()
    override func viewDidLoad() {
        super.viewDidLoad()
        startLocationManager()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    internal func startLocationManager(){
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.delegate = self
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.startUpdatingLocation()
    }

}

extension ViewController : CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
        let location = locations[0] as CLLocation
        print(location.coordinate.latitude) // prints user's latitude
        print(location.coordinate.longitude) //will print user's longitude
        print(location.speed) //will print user's speed
    }

}

0

मानक स्थान सेवाओं का उपयोग करने के लिए जब एप्लिकेशन पृष्ठभूमि में हो, तो आपको लक्ष्य सेटिंग्स की क्षमता टैब में पृष्ठभूमि मोड पर पहली बारी चाहिए, और स्थान अपडेट का चयन करें।

या, इसे सीधे Info.plist में जोड़ें ।

<key>NSLocationAlwaysUsageDescription</key>
 <string>I want to get your location Information in background</string>
<key>UIBackgroundModes</key>
 <array><string>location</string> </array>

फिर आपको CLLocationManager को सेटअप करने की आवश्यकता है

उद्देश्य सी

//The Location Manager must have a strong reference to it.
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
//Request Always authorization (iOS8+)
if ([_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { [_locationManager requestAlwaysAuthorization];
}
//Allow location updates in the background (iOS9+)
if ([_locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) { _locationManager.allowsBackgroundLocationUpdates = YES;
}
[_locationManager startUpdatingLocation];

तीव्र

self.locationManager.delegate = self
if #available (iOS 8.0,*) {
    self.locationManager.requestAlwaysAuthorization()
}
if #available (iOS 9.0,*) {
    self.locationManager.allowsBackgroundLocationUpdates = true
}
self.locationManager.startUpdatingLocation()

Ref: https://medium.com/@javedmultani16/location-service-in-the-background-ios-942c89cd99ba


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.