ios 应用程序未运行时的 iBeacon 通知
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19127282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iBeacon Notification when the app is not running
提问by Lapidus
I managed to make an iBeacon which triggers a local push notification on my iPhone when the beacon is in range. It's perfectly working when the app is in background mode.
我设法制作了一个 iBeacon,当信标在范围内时,它会在我的 iPhone 上触发本地推送通知。当应用程序处于后台模式时,它完美地工作。
My question is: Can I trigger the notification even when the app is not running, not even in the background?
我的问题是:即使应用程序没有运行,甚至在后台也没有运行,我是否可以触发通知?
I thought this was possible but I'm not sure. If so, how can I accomplish this?
我认为这是可能的,但我不确定。如果是这样,我怎样才能做到这一点?
Thanks!
谢谢!
回答by davidgyoung
Yes, it's possible and should be automatic.
是的,这是可能的,应该是自动的。
After you have created a CLBeaconRegion and started monitoring on it, Location Services will keep track of whether your phone is in or out of the region, even when your app isn't running. If you app isn't running during a transition, iOS will launch your app into the background for a few seconds to call the appropriate CLLocationManagerDelegate methods.
在您创建了 CLBeaconRegion 并开始对其进行监控后,位置服务将跟踪您的手机是在该区域内还是在该区域外,即使您的应用程序未运行也是如此。如果您的应用程序在转换期间没有运行,iOS 会将您的应用程序启动到后台几秒钟以调用适当的 CLLocationManagerDelegate 方法。
I found out the above behavior through experimentation with my own app, but have also witnessed it with Apple's AirLocate sample program. With AirLocate, if you set up a monitoring region then reboot your phone, AirLocate will still deliver a local notification as soon as the phone enters the region.
我通过我自己的应用程序的实验发现了上述行为,但也通过 Apple 的 AirLocate 示例程序见证了它。使用AirLocate,如果您设置了监控区域然后重启手机,AirLocate 仍然会在手机进入该区域后立即发送本地通知。
Take care when testing this, because sometimes it takes up to 4 minutes after turning on/off an iBeacon before iOS recognizes the region state transition. EDIT: As of the iPhone 5, apps will typically use hardware acceleration to detect beacons within a few seconds, and if hardware acceleration is not available, it can take up to 15 minutes.
测试时要小心,因为有时在打开/关闭 iBeacon 后 iOS 识别区域状态转换之前需要长达 4 分钟。 编辑:从 iPhone 5 开始,应用程序通常会在几秒钟内使用硬件加速来检测信标,如果硬件加速不可用,则最多可能需要 15 分钟。
EDIT 3:AS of iOS 13, you must make sure the user actually grants background permission and not "only once" or "when in use" permission which are heavily pushed by the operating system in the dialogs they present to the user. See herefor details.
编辑 3:从 iOS 13 开始,您必须确保用户实际授予后台权限,而不是“仅一次”或“使用时”权限,这些权限是操作系统在向用户显示的对话框中大量推送的。有关详细信息,请参见此处。
EDIT 2:As of iOS 8, you need to make sure you have called and successfully obtained locationManager.requestAlwaysAuthorization()
as locationManager.requestWhenInUseAuthorization()
only lets beacons be detected in the foreground.
编辑 2:从 iOS 8 开始,您需要确保已调用并成功获取,locationManager.requestAlwaysAuthorization()
因为locationManager.requestWhenInUseAuthorization()
只允许在前台检测到信标。
I have posted a detailed discussion on how this all works in this blog post.
回答by TNBtech
OK I've gotten this to work correctly and experimented around with it so here is the answer. This is what you need to do to get your app to be invoked when crossing a beacon region boundary after the app has been terminated (assuming your app works properly when in the foreground):
好的,我已经让它正常工作并对其进行了试验,所以这就是答案。这是在应用程序终止后跨越信标区域边界时调用应用程序所需的操作(假设您的应用程序在前台运行正常):
- You must implement a
CLLocation
delegate inside yourAppDelegate.m
module. This delegate is what gets invoked by iOS so if you don't have theCLLocation
delegate code inAppDelegate.m
, you won't be able to respond to iOS when your app has been terminated. This is what Apple's AirLocate sample app does.
- 你必须在你的模块中实现一个
CLLocation
委托。这个委托是由 iOS 调用的,所以如果您没有委托代码,当您的应用程序终止时,您将无法响应 iOS。这就是 Apple 的 AirLocate 示例应用程序所做的。AppDelegate.m
CLLocation
AppDelegate.m
So, inside AppDelegate.m
you need the following (you also need to link in CoreLocation.h
):
所以,在里面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;
}
Inside
AppDelegate.m
, you need to implement the locationManager didDetermineStatemethod, like this:-(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]; }
在里面
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]; }
--> So if your app has been terminated (it must be run at least ONCE), when the device transitions across a beacon boundary that you are monitoring, iOS will invoke your app and call the locationManager:didDetermineState
method in your AppDelegate.m module. Inside this method you can then set up and call presentLocalNotificationNow. If your app is NOT in the foreground when this happens, iOS will present the notification on the screen even if it is locked. The user will then have to invoke the app for more information.
--> 因此,如果您的应用程序已终止(它必须至少运行一次),当设备过渡到您正在监视的信标边界时,iOS 将调用您的应用程序并调用locationManager:didDetermineState
AppDelegate.m 模块中的方法。在此方法中,您可以设置并调用presentLocalNotificationNow。如果发生这种情况时您的应用程序不在前台,即使它被锁定,iOS 也会在屏幕上显示通知。然后,用户必须调用该应用程序以获取更多信息。
I'm pretty sure that memory pressure has nothing to do with this. Also, the setting notifyEntryStateOnDisplay
has nothing to do this this issue either. Setting notifyEntryStateOnDisplay
is only used when the user turns on the iOS device display (ie hits "home" or top left button). If the user does this and notifyEntryStateOnDisplay
is TRUE
, AND the device is INSIDE the beacon region you are monitoring for, THEN you get a notification on the display at that time. If this property is set to FALSE
, you don't.
我很确定内存压力与此无关。此外,设置notifyEntryStateOnDisplay
也与此问题无关。设置notifyEntryStateOnDisplay
仅在用户打开 iOS 设备显示时使用(即点击“主页”或左上角按钮)。如果用户这样做并且notifyEntryStateOnDisplay
是TRUE
,并且设备位于您正在监视的信标区域内,那么您会在那时在显示屏上收到通知。如果此属性设置为FALSE
,则不会。
Of course, you need to be running iOS 7.1 in order for this stuff to work correctly.
当然,您需要运行 iOS 7.1 才能使这些东西正常工作。
For more details, visit Apple's documentation
有关更多详细信息,请访问 Apple 的文档
回答by Jian Yin Shen
You need to switch notifyEntryStateOnDisplay=YES for CLBeaconRegion for the system to wake your app for iBeacon entry/exit event.
您需要为 CLBeaconRegion 切换 notifyEntryStateOnDisplay=YES 以使系统唤醒您的应用程序以进行 iBeacon 进入/退出事件。
But there is one tricky part. If your app is not running the system will only wake your app for beacon entry/exit handling if your app was terminated previously due to system memory pressure.If the user kills the app by swiping it up in the task view, the system will not wake your app. To verify this behaviour, launch you app, put it to background, then consecutively launch several memory consuming apps. I launched several 3D games before my app gets terminated by the system due to memory pressure.
但有一个棘手的部分。如果您的应用程序未运行,系统只会在您的应用程序之前因系统内存压力而终止的情况下唤醒您的应用程序以进行信标进入/退出处理。如果用户通过在任务视图中向上滑动来杀死应用程序,系统将不会唤醒您的应用程序。要验证此行为,请启动您的应用程序,将其置于后台,然后连续启动多个内存消耗应用程序。由于内存压力,在我的应用程序被系统终止之前,我启动了几个 3D 游戏。
回答by Hugh Mbaezue
Just upgrade your iOS version to 7.1 and set "notifyEntryStateOnDisplay=YES" and it should work like a charm even when your app is not running. I was having this problem earlier but it got fixed once I did this upgrade! Enjoy..
只需将您的 iOS 版本升级到 7.1 并设置“notifyEntryStateOnDisplay=YES”,即使您的应用程序未运行,它也应该像魅力一样工作。我之前遇到过这个问题,但在我升级后它得到了修复!享受..
回答by Ronny Khan
The only way I have been able to make this work is by monitoring for major location changes which seem to do the trick. Be warned I have not tested this for all of the device or use case scenarios.
我能够完成这项工作的唯一方法是监视主要的位置变化,这似乎可以解决问题。请注意,我尚未针对所有设备或用例场景对此进行测试。
回答by Gautam Sareriya
Yes, we can present the local notification in kill state or in the background state, just follow the steps,
是的,我们可以在kill状态或后台状态呈现本地通知,只需按照步骤,
1) Start location manager using CLLocationManager class.
1) 使用 CLLocationManager 类启动位置管理器。
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=kCLDistanceFilterNone;
2) Create CLBeaconRegion like,
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) Implement two location manager delegate method like,
3)实现两个位置管理器委托方法,如,
-didEnterRegion
-didExitRegion
The above two location manager method will work even your app is kill or in background. The system will keep track of your beacon and when it goes out of the range the system will fire the didExitRegion method and when comes in the system will fire the didEnterRegion method.
即使您的应用程序被终止或在后台,上述两种位置管理器方法也能正常工作。系统将跟踪您的信标,当它超出范围时,系统将触发 didExitRegion 方法,当进入时,系统将触发 didEnterRegion 方法。