簡體   English   中英

信標在iOS上的后台測距

[英]Beacon Ranging in Background on iOS

我了解監視和測距之間的區別,並且了解iOS的局限性,因為信標測距只能在進入和退出區域時在前台或后台進行,如此處所述( http://developer.radiusnetworks.com/2013 /11/13/ibeacon-monitoring-in-the-background-and-foreground.html )。 但是我試圖找出如何解決一個常見的情況。

如果我在百貨商店中安裝了一堆信標,我應該如何檢測一個人何時在這些信標范圍內移動? 通過當前的工作方式,該應用程序將在用戶進入商店( didEnterRegion )時獲得一個事件,因為所有信標的集合都充當一個大區域。 但是,除非信標放置得足夠遠,以使用戶能夠退出並再次進入該區域,否則無法知道用戶正在商店的不同區域之間移動,這可能不切實際。

我想在后台范圍內設置信標的原因是,我可能需要知道用戶在商店中的特定板塊/產品上,以顯示該板塊的特定要約/信息(通過通知),而無需用戶進行操作。打開應用程序。

在我看來,這似乎是購物中心和博物館等的一種非常常見的情況。。。我想知道其他開發商如何解決這個問題,或者是否有實現我想要的目標的另一種方法。

我沒有在此處包括代碼片段,因為問題不在於代碼,而只是概念上的問題。 如果需要任何澄清或代碼,我也可以添加。

謝謝

答案的最大部分是我的同事@csexton在對該問題的另一個答案中記錄的技術。

為了解決第二個問題,即過渡后僅獲得10秒的測距時間,您可以請求額外的時間來保持測距。 iOS允許您在后台繼續進行長達180秒的測距。 這不需要后台模式,也不需要AppStore的特殊許可。

設置方法如下:

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    if (_inBackground) {
        [self extendBackgroundRunningTime];
    }
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [self logString: [NSString stringWithFormat:@"applicationDidEnterBackground"]];
    [self extendBackgroundRunningTime];
    _inBackground = YES;
}


- (void)extendBackgroundRunningTime {
    if (_backgroundTask != UIBackgroundTaskInvalid) {
        // if we are in here, that means the background task is already running.
        // don't restart it.
        return;
    }
    NSLog(@"Attempting to extend background running time");

    __block Boolean self_terminate = YES;

    _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"DummyTask" expirationHandler:^{
        NSLog(@"Background task expired by iOS");
        if (self_terminate) {
            [[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
            _backgroundTask = UIBackgroundTaskInvalid;
        }
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Background task started");

        while (true) {
            NSLog(@"background time remaining: %8.2f", [UIApplication sharedApplication].backgroundTimeRemaining);
            [NSThread sleepForTimeInterval:1];
        }

    });
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [self logString: [NSString stringWithFormat:@"applicationDidBecomeActive"]];
    _inBackground = NO;
}

在后台達到180秒的范圍並不是靈丹妙葯,但是它可以解決許多10秒沒有的用例。

您可以在此處閱讀有關其工作原理的完整文章以及測試結果: https : //github.com/RadiusNetworks/ibeacon-background-demo/tree/background-task

我可能會通過將商店分成多個區域來對此建模。 它們的建模方式將基於觸發通知時的用例。

我可以通過給他們全部相同的UUID,但使用不同的Major值來實現。 然后使用次要值來區分存儲。 這樣,當他們從區域移動時,應用程序將注冊didEnter事件。

您可以注冊大約20個區域,因此將信標分組在一起時要格外小心。

例如:

  • UUID: 754A5D70-C59E-4E39-AA56-ED646903EF5B專業: 1 →入口
  • UUID: 754A5D70-C59E-4E39-AA56-ED646903EF5B專業: 2 →收銀機
  • UUID: 754A5D70-C59E-4E39-AA56-ED646903EF5B專業: 3 →服裝
  • UUID: 754A5D70-C59E-4E39-AA56-ED646903EF5B專業: 4 →家庭用品
  • ...

然后,當應用程序的用戶在商店中移動時,您可以在跨越區域邊界時觸發操作。

這樣,您可以:

  1. 獲取輸入和退出回調
  2. 開始進行排序以找出次要值(每個商店可能是次要值,或者每個信標可​​能是唯一值)
  3. 發送本地通知

您需要做的是確保所有信標都具有相同的UUID。 然后,注冊一個用於監視的CLBeaconRegion,它僅指定該UUID。 不要包含主要或次要值。 當輸入與UUID匹配的didEnterRegion:標時,將調用didEnterRegion:通配符大和小值)。 但是,此處返回的CLBeaconRegion將僅具有UUID,而沒有主要/次要的名稱,就像您注冊它的方式一樣,因此您不知道確切觸發了哪個信標。 為了准確確定設備正在查看哪個信標,在didEnterRegion:時,告訴位置管理器使用輸入的區域來startRangingBeaconsInRegion: 然后,位置管理器將使用didRangeBeacons:致電給您didRangeBeacons:傳遞一個CLBeacons數組。 這些CLBeacon將知道其主要值和次要值,您可以從中准確確定用戶所在的商店的一部分(因為您知道該主要/次要對象的信標部署在何處)。 可以在應用程序處於后台時完成所有操作。

這樣,您僅注冊一個CLBeaconRegion,但仍可以與匹配已注冊UUID的任何信標交互。

我已經使用這種方法在一個區域內成功部署了80多個信標,並成功在前景和背景中觸發了這些信標。 您不需要用戶打開應用程序即可完成此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM