57

我设法制作了一个 iBeacon,当信标在范围内时,它会在我的 iPhone 上触发本地推送通知。当应用程序处于后台模式时,它可以完美运行。

我的问题是:即使应用程序没有运行,即使在后台也不能触发通知?

我认为这是可能的,但我不确定。如果是这样,我该如何做到这一点?

谢谢!

4

6 回答 6

67

是的,这是可能的并且应该是自动的。

在您创建 CLBeaconRegion 并开始对其进行监控后,定位服务将跟踪您的手机是否在该区域内,即使您的应用程序未运行也是如此。如果您的应用在过渡期间没有运行,iOS 将在几秒钟内将您的应用启动到后台以调用适当的 CLLocationManagerDelegate 方法。

我通过自己的应用程序实验发现了上述行为,但也通过 Apple 的 AirLocate 示例程序见证了它。使用 AirLocate,如果您设置了监控区域然后重启手机,只要手机进入该区域,AirLocate 仍会发送本地通知。

测试时要小心,因为有时在打开/关闭 iBeacon 后最多需要 4 分钟,iOS 才能识别区域状态转换。 编辑:从 iPhone 5 开始,应用程序通常会在几秒钟内使用硬件加速来检测信标,如果硬件加速不可用,则可能需要长达 15 分钟。

编辑 3:从 iOS 13 开始,您必须确保用户实际授予后台权限,而不是“仅一次”或“使用时”权限,这些权限在他们呈现给用户的对话框中由操作系统大量推送。有关详细信息,请参见此处

编辑 2: 从 iOS 8 开始,您需要确保已调用并成功获取locationManager.requestAlwaysAuthorization(),因为locationManager.requestWhenInUseAuthorization()仅允许在前台检测到信标。

我已经在这篇博文中详细讨论了这一切是如何运作的。

于 2013-10-02T01:47:29.057 回答
18

好的,我已经让它正常工作并进行了试验,所以这就是答案。这是在应用程序终止后越过信标区域边界时调用应用程序所需执行的操作(假设您的应用程序在前台正常工作):

  1. 你必须在你的模块CLLocation中实现一个委托。这个委托是由 iOS 调用的,所以如果你没有委托代码,当你的应用程序被终止时,你将无法响应 iOS。这就是 Apple 的 AirLocate 示例应用程序所做的。AppDelegate.mCLLocationAppDelegate.m

所以,在里面AppDelegate.m你需要以下内容(你还需要链接CoreLocation.h):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.

// This location manager will be used to notify the user of region state transitions when the app has been previously terminated.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
return YES;
}
  1. 在里面AppDelegate.m,你需要实现locationManager didDetermineState方法,像这样:

    -(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
    
      UILocalNotification *notification = [[UILocalNotification alloc] init];
    
      if(state == CLRegionStateInside)
      {
        notification.alertBody = [NSString stringWithFormat:@"You are inside region %@", region.identifier];
      }
      else if(state == CLRegionStateOutside)
      {
        notification.alertBody = [NSString stringWithFormat:@"You are outside region %@", region.identifier];
      }
     else
     {
       return;
     }
    
      [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
     }
    

--> 因此,如果您的应用程序已终止(它必须至少运行一次),当设备跨越您正在监视的信标边界时,iOS 将调用您的应用程序并调用locationManager:didDetermineStateAppDelegate.m 模块中的方法。在此方法中,您可以设置并调用 presentLocalNotificationNow。如果发生这种情况时您的应用程序不在前台,iOS 将在屏幕上显示通知,即使它已被锁定。然后,用户将不得不调用该应用程序以获取更多信息。

我很确定内存压力与此无关。此外,该设置notifyEntryStateOnDisplay也与此问题无关。设置notifyEntryStateOnDisplay仅在用户打开 iOS 设备显示屏时使用(即点击“主页”或左上角按钮)。如果用户这样做并且notifyEntryStateOnDisplayTRUE,并且设备位于您正在监视的信标区域内,那么您当时会在显示屏上收到通知。如果此属性设置为FALSE,则不需要。

当然,您需要运行 iOS 7.1 才能使这些东西正常工作。

有关更多详细信息,请访问 Apple 的文档

于 2014-03-19T19:04:27.740 回答
10

您需要为 CLBeaconRegion 切换 notifyEntryStateOnDisplay=YES 以便系统为 iBeacon 进入/退出事件唤醒您的应用程序。

但有一个棘手的部分。如果您的应用程序未运行,则系统只会在您的应用程序之前因系统内存压力而终止的情况下唤醒您的应用程序以进行信标进入/退出处理。如果用户通过在任务视图中向上滑动来终止应用程序,系统将不会唤醒您的应用程序。要验证此行为,请启动您的应用程序,将其置于后台,然后连续启动多个内存消耗应用程序。在我的应用程序因内存压力而被系统终止之前,我启动了几个 3D 游戏。

于 2014-02-06T00:25:21.350 回答
6

只需将您的 iOS 版本升级到 7.1 并设置“notifyEntryStateOnDisplay=YES”,即使您的应用程序未运行,它也应该像魅力一样工作。我之前遇到过这个问题,但是一旦我进行了升级,它就得到了解决!享受..

于 2014-03-11T16:14:59.097 回答
2

我能够完成这项工作的唯一方法是监视似乎可以解决问题的主要位置变化。请注意,我尚未针对所有设备或用例场景对此进行测试。

于 2013-10-26T20:18:18.173 回答
2

是的,我们可以在杀死状态或后台状态下显示本地通知,只需按照步骤操作,

1) 使用 CLLocationManager 类启动位置管理器。

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=kCLDistanceFilterNone;

2)创建 CLBeaconRegion 之类的,

CLBeaconRegion *beacon_Region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:mjorVa minor:minorVa identifier:identifier];
beacon_Region.notifyEntryStateOnDisplay = YES;
beacon_Region.notifyOnEntry=YES;
beacon_Region.notifyOnExit=YES;

3)实现两个位置管理器委托方法,如,

-didEnterRegion
-didExitRegion

即使您的应用程序被杀死或在后台,上述两种位置管理器方法也将起作用。系统将跟踪您的信标,当它超出范围时,系统将触发 didExitRegion 方法,当进入范围时,系统将触发 didEnterRegion 方法。

于 2015-11-05T10:45:58.657 回答