我成功制作了一个iBeacon,在我的iPhone进入beacon的覆盖范围时触发本地推送通知,当应用程序在后台模式下运行时,完美运作。
我的问题是:即使应用程序没有运行,甚至不在后台模式下,我是否可以触发通知?
我认为这是可能的,但我不确定。如果是这样,我该如何实现呢?
谢谢!
我成功制作了一个iBeacon,在我的iPhone进入beacon的覆盖范围时触发本地推送通知,当应用程序在后台模式下运行时,完美运作。
我的问题是:即使应用程序没有运行,甚至不在后台模式下,我是否可以触发通知?
我认为这是可能的,但我不确定。如果是这样,我该如何实现呢?
谢谢!
是的,这是可能的,并且应该是自动的。
当你创建了一个CLBeaconRegion并开始对其进行监控后,位置服务会跟踪你的手机是否在区域内,即使你的应用程序没有运行。如果你的应用程序在转换期间没有运行,iOS将在后台启动你的应用程序几秒钟,以调用相应的CLLocationManagerDelegate方法。
我通过我的应用程序实验发现了上述行为,但也通过Apple的AirLocate示例程序进行了观察。使用AirLocate,如果您设置了一个监控区域,然后重新启动您的手机,AirLocate仍然会在手机进入该区域后立即发送本地通知。
测试时要小心,因为有时需要在打开/关闭iBeacon后等待长达4分钟,iOS才能识别区域状态转换。 编辑: 自iPhone 5以来,应用程序通常会利用硬件加速在几秒钟内检测到iBeacon,如果硬件加速不可用,则可能需要长达15分钟。
编辑3:从iOS 13开始,您必须确保用户实际授予后台权限,而不是操作系统在向用户呈现的对话框中大力推广的“仅一次”或“使用时”权限。有关详细信息,请参见此处。
编辑2:从iOS 8开始,您需要确保已经调用并成功获取了locationManager.requestAlwaysAuthorization()
,因为locationManager.requestWhenInUseAuthorization()
只允许在前台检测信标。
我在这篇博客文章中发表了关于所有这些内容如何工作的详细讨论。
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
会被触发,但 didEnterRegion
不会。我已将逻辑移到了那个方法中。非常奇怪。 - Ted Avery好的,我已经成功地解决了这个问题,并对其进行了实验,下面是答案。如果您的应用在前台运行时正常工作(假设),则需要执行以下操作才能在应用程序终止后越过信标区域边界时调用您的应用程序:
AppDelegate.m
模块内实现一个 CLLocation
委托。这个委托是由 iOS 调用的,所以如果您没有在 AppDelegate.m
中编写 CLLocation
委托代码,您将无法响应iOS通知应用程序已被终止。 这是 Apple 的 AirLocate 示例应用程序的做法。因此,在 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;
}
在 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:didDetermineState
方法并在您的AppDelegate.m模块中调用。在这个方法中,您可以设置和调用presentLocalNotificationNow。如果此时您的应用程序不在前台,则即使锁定了屏幕,iOS也会在屏幕上呈现通知。然后用户将需要调用该应用程序以获取更多信息。
我很确定内存压力与此无关。另外,设置notifyEntryStateOnDisplay
也与此问题无关。仅当用户打开iOS设备显示器(即按“主页”或左上角按钮)时,才会使用notifyEntryStateOnDisplay
。如果用户执行此操作并且notifyEntryStateOnDisplay
为TRUE
,并且设备位于您正在监视的信标区域内,则会在此时在显示器上收到通知。如果将此属性设置为FALSE
,则不会。
当然,您需要运行iOS 7.1才能正确地执行此操作。
有关详细信息,请访问苹果公司的文档。
class_addMethod
和class_addProtocol
可以动态地将CLLocationManagerDelegate
协议添加到AppDelegate
中吗? - Joe Beuckman您需要将CLBeaconRegion的notifyEntryStateOnDisplay设置为YES,系统才能在iBeacon进出事件时唤醒您的应用程序。
但是有一个棘手的部分。如果您的应用程序未运行,则在处理信标进入/退出时,系统只会唤醒您的应用程序如果您的应用程序之前因系统内存压力而被终止。 如果用户通过向上滑动任务视图中的应用程序来杀死应用程序,则系统将不会唤醒您的应用程序。为了验证此行为,请启动您的应用程序,将其放到后台,然后连续启动几个消耗内存的应用程序。我在我的应用程序被系统由于内存压力而终止之前启动了几个3D游戏。
只需将您的iOS版本升级到7.1并设置“notifyEntryStateOnDisplay=YES”,即使您的应用程序未运行,它也应该像魔术般工作。我之前遇到了这个问题,但一旦我升级了系统,问题就解决了!享受吧..
是的,我们可以在应用被杀死或后台状态下展示本地通知,只需要按照以下步骤操作:
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方法。
requestStateForRegion:
е®һдҫӢж–№жі•жқҘзЎ®е®ҡеә”з”ЁзЁӢеәҸеҗҜеҠЁж—¶дҪ жҳҜеҗҰеңЁеҢәеҹҹеҶ…жҲ–еӨ–гҖӮ - Tobias