【问题标题】:iBeacon send notification for multiple beaconiBeacon 为多个信标发送通知
【发布时间】:2014-06-27 04:12:16
【问题描述】:

场景

我在同一条街上有 3 个商家。每个商人都有一个信标。我希望最终用户在靠近 (CLProximityNear) 时收到通知。

源代码

AppDelegate.m

self.iBeaconManager = [[CLLocationManager alloc] init];
self.iBeaconManager.delegate = self;

NSUUID *proximityUUID = [[NSUUID alloc] initWithUUIDString:@"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];

CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:proximityUUID identifier:@"BeaconIdentifier"];
region.notifyEntryStateOnDisplay = YES;

[self.iBeaconManager startMonitoringForRegion:region];

委托

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
    [self.iBeaconManager requestStateForRegion:region];
}

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    UILocalNotification *notification = [[UILocalNotification alloc] init];

    switch (state) {
        case CLRegionStateInside: {
            [self.iBeaconManager startRangingBeaconsInRegion:region];

            notification.alertBody = [NSString stringWithFormat:@"You are inside region %@", region.identifier];
            break;
        }

        case CLRegionStateOutside:
            notification.alertBody = [NSString stringWithFormat:@"You are outside region %@", region.identifier];
        case CLRegionStateUnknown:
        default:
            NSLog(@"Region unknown");
    }

    notification.soundName = UILocalNotificationDefaultSoundName;
    [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    if ([beacons count] > 0) {
        for (CLBeacon *beacon in beacons) {

            NSMutableString *logText = [NSMutableString stringWithFormat:@"Beacon: major: %d minor: %d Distance: %f is", [beacon.major intValue], [beacon.minor intValue], beacon.accuracy];

            switch (beacon.proximity) {
                case CLProximityImmediate: // 0 - 20cm
                    [logText appendString:@" IMMEDIATE"];

                    break;

                case CLProximityNear: // 20cm - 2m
                    [logText appendString:@" NEAR"];

                    break;

                case CLProximityFar: // 2m - 70m
                    [logText appendString:@" FAR"];
                    break;

                default:
                    [logText appendString:@" UNKNOWN"];
                    break;
            }
            UILocalNotification *notification = [[UILocalNotification alloc] init];
            notification.alertBody = logText;
            notification.soundName = UILocalNotificationDefaultSoundName;
            [[UIApplication sharedApplication] scheduleLocalNotification:notification];
        }
    }
}

问题

当我靠近信标时,我会收到无限的通知

问题

我希望这些最终用户在靠近时只收到一个通知。

例如您好,欢迎光临 A 店,我们只提供今天的超值折扣

然后当他们走远了,再次通知感谢您的光临。祝你有美好的一天

我应该将那个特定商家(信标)的当前状态/邻近度保存到NSUserDefaults吗?其实我试过了

CLProximity currentProximity = ... // 从保存在 NSUserDefaults 中的特定信标获取接近度

switch (beacon.proximity) {
    case CLProximityImmediate: // 0 - 20cm
        [logText appendString:@" IMMEDIATE"];
        // if 1 second ago is Immediate, now still immediate
        if (currentProximity == CLProximityImmediate) continue;
        currentProximity = CLProximityImmediate;

        break;
    ...
}

修改上面的代码后,当我按下主页按钮时没有收到通知(应用程序在后台运行)

编辑

我认为问题在于当应用程序在后台运行时,USUserDefaults 实际上无法正常工作。即使应用程序根本没有运行,我也想保持每个信标的接近状态。

有什么建议吗?

【问题讨论】:

    标签: ios objective-c notifications ibeacon


    【解决方案1】:

    你需要在这里做一些逻辑。

    您应该为所有 iBeacon 设置标志。当一个特定的 iBeacons 靠近时,您应该设置这个 iBeacons 靠近的标志。 CLProximityNear

    当它到达远处时,标志将关闭CLProximityFar

    所以你需要执行以下步骤。

    1. 将所有 iBeacons 的标志设置为接近时(显示通知)。
    2. 标记何时走远。

    确保您需要管理单独标志的所有 iBeacon

    【讨论】:

    • 我试图为所有信标保留CLProximity,但是一旦我添加if (currentProximity == CLProximityImmediate) continue;,当应用程序在后台运行时它就完全没有通知了。仅当应用程序在前台运行时才有效
    • Sunny 的解决方案是好的,只要应用程序在前台。但正如 Yatheesha 所提到的,在进入区域后超过 5 秒,测距将无法在后台工作。不幸的是,这个用例根本不能在后台工作,因为用户通常在远处进入该区域,并且没有足够的背景测距时间可以变得靠近。由于大多数用户不会将应用程序置于前台,因此我会重新考虑这一点。
    • @davidgyoung 你确定测距不会在后台工作吗?因为我已经在后台在 ios 7.1 中进行了测试,所以我已经做到了。
    • @SunnyShah 看看这个链接developer.radiusnetworks.com/2013/11/13/…
    • @davidgyoung 实际上locationManager:didRangeBeacons:inRegion: 即使应用程序没有运行也可以工作。今天早上刚上任,突然收到一大堆通知,而且我的应用甚至不在后台
    【解决方案2】:

    了解它将在后台运行,但仅在您的应用被事件唤醒到后台后大约 5 秒。这些事件可以包括信标区域进入/退出、接收推送通知、点亮显示器等。每个事件都需要不同的设置来获取它。

    【讨论】:

    • 你是对的,它只持续了大约 5 秒。似乎对这项技术有一定的限制。希望以后有进步
    【解决方案3】:

    我写了一个answer 来回答一个可能对你有用的类似问题。

    基本上,Apple 不希望您在后台进行测距,因此排除了您可以进行的任何近距离读取。当然,这并不意味着你不能这样做,但你应该这样做吗?

    您可以用来限制通知的一种解决方案是跟踪应用徽章的数量。

    BOOL isNoAppBadges = ([[UIApplication sharedApplication]
                          applicationIconBadgeNumber] == 0);
    BOOL isApplicationInBackground = ([[UIApplication sharedApplication]
                          applicationState] == UIApplicationStateBackground);
    

    然后

            if (isNoAppBadges &&
                isApplicationInBackground)
            {
                // Red badge that appears over the app icon
                [[UIApplication sharedApplication]
                 setApplicationIconBadgeNumber:1];
    
                UILocalNotification *notification = [
                                        [UILocalNotification alloc] init];
    
                notification.alertBody = @"Your notification text";
    
                [[UIApplication sharedApplication]
                 presentLocalNotificationNow:notification];
            }
    

    这个逻辑已经进去了:

    - (void)locationManager:(CLLocationManager *)manager
      didDetermineState:(CLRegionState)state
              forRegion:(CLRegion *)region
    

    当应用程序处于前台时显示通知可能没有多大意义,但为了保持主题的答案,您可以使用上述逻辑:

    - (void)locationManager:(CLLocationManager *)manager
        didRangeBeacons:(NSArray *)beacons
               inRegion:(CLBeaconRegion *)region
    

    并实现您在示例中所做的相同 switch 语句。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      相关资源
      最近更新 更多