如何在iOS上使用基于地理位置的推送通知?

24

当应用程序被杀掉(不在后台运行)时,iOS是否可以利用基于地理位置的推送通知功能?

我有兴趣开发一个应用程序,在该应用程序中,用户将在地图上选择一个位置,然后如果他/她接近该区域,本地的基于地理位置的推送通知将会被触发。

然而,这个“想法”是否可行呢?当应用程序被杀掉时,GPS是否可以运行并比较坐标,并在用户到达目的地时通知用户?是否有任何关于这个主题的教程/文章/更多信息可以阅读?

我在网上读到的大部分信息更像是实现的一般思路,没有具体涉及该问题。


为什么你不想在后台运行应用程序(即在杀死应用程序后)?我在我的应用程序中应用了相同的概念,具有后台运行功能。你能详细说明一下吗? - Arpit Kulsreshtha
例如,假设用户设置了一个提醒,他想在下周去他奶奶家时看到它。但是手机可能会被重置或者他可能已经从后台删除了应用程序。因此,我需要即使应用程序未在后台运行也能触发推送。你能告诉我应用程序的名称吗?我非常想看看你实现了什么 :) - donparalias
  1. 应用程序关闭后,GPS 就不再运行,因此不可能使用。
  2. 当您在 CMS 中注释一个示例时,您可以在提醒时间上设置推送通知。 在 Web 服务中,您可以设计一个算法,以便在移动提醒上设置推送通知。
- Arpit Kulsreshtha
1个回答

34

要在应用程序未运行时(即之前已终止)跟踪用户的位置,有两个选项:

  1. 根据“跟踪用户位置”下的iOS 应用程序编程指南

    极力推荐使用显著变化位置服务以获取不需要高精度位置数据的应用程序。使用此服务时,仅当用户位置发生显著更改时才会生成位置更新;因此,它非常适合社交应用程序或提供用户非关键位置相关信息的应用程序。如果应用程序在更新发生时处于挂起状态,则系统会在后台唤醒它以处理更新。如果应用程序启动了此服务并被终止,则系统会在新位置可用时自动重新启动应用程序。 此服务适用于 iOS 4 及以上版本,并且仅适用于包含蜂窝无线电的设备。

    但是,根据CLLocationManager 类引用,其精度不高且更新不频繁:

    注意:设备从其先前通知的位置移动500米或更多时,应用程序可以期望收到通知。它不应该比每5分钟一次更频繁地收到通知。如果设备能够从网络检索数据,则位置管理器更有可能及时提供通知。

  2. 区域监控以类似的方式工作-在被终止后重新启动应用程序-但具有更高的精确度(取决于 Wifi 网络和蜂塔可用性):

    特定阈值距离由当前可用的硬件和位置技术确定。例如,如果 Wi-Fi 被禁用,则区域监视明显不准确。但是,出于测试目的,您可以假设最小距离约为200米。

    另一个区域监控的考虑因素是(根据CLLocationManager 类引用),在穿过区域边界后可能仅在3-5分钟左右才会收到区域进入和退出通知。

    根据实际要求,可以使用区域监控获取“粗略”位置,然后当用户在特定区域内时,启动基于 GPS 的更准确的位置管理器服务。当用户离开感兴趣的区域时,关闭 GPS 服务以节省电池电量,并再次转换为粗略位置监视服务(即区域监控)。以下是基本实现:

    SomeViewController.m

...
@interface SomeViewController () <CLLocationManagerDelegate>

@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, strong) CLRegion *someRegion;

@end

@implementation SomeViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.locationManager = [[CLLocationManager alloc] init];

    CLLocationDistance radius = 10; // 10 metre sensitivity
    self.someRegion = [[CLRegion alloc] initCircularRegionWithCenter:someCoordinates radius:radius identifier:@"Smithtown Dry Cleaners"];

    self.locationManager.delegate = self;
    [self.locationManager startMonitoringForRegion:self.someRegion];

    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.distanceFilter = 10;
    [self.locationManager startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    [self.locationManager startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    [self.locationManager stopUpdatingLocation];
}

// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation* location = [locations lastObject];

    // If the user's current location is not within the region anymore, stop updating
    if ([self.someRegion containsCoordinate:location.coordinate] == NO) {
        [self.locationManager stopUpdatingLocation];
    }

    NSString *locationData = [NSString stringWithFormat:@"latitude %+.6f, longitude %+.6f\n",
                              location.coordinate.latitude,
                              location.coordinate.longitude];
    NSLog(@"%@", locationData);

    UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    localNotification.alertBody = locationData;
    localNotification.alertAction = @"Location data received";
    localNotification.hasAction = YES;
    [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}

请记得将相应的条目添加到应用程序的plist文件中,这样应用程序就可以在后台运行,并访问适当的资源:

MyApp-Info.plist:

<key>UIBackgroundModes</key>
<array>
        ...
        <string>location</string>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
        ...
        <string>location-services</string>
        <string>gps</string>
</array>

上面的代码假设使用iOS6和ARC


由于重大更改位置服务依赖于设备更改基站,因此可能不够好。 - gavdotnet
嗯,我猜唯一的方法就是让应用程序在后台运行了。 - donparalias
1
如果应用程序在终止之前启动了“区域监视”或“重大位置更改监视”,则当位置发生足够的更改时,应用程序将在后台重新启动,并调用委托方法locationManager:didUpdateLocations:。 - gavdotnet
1
@donparalias:是的和不是。应用程序需要在前台或后台运行才能使用GPS。但是...iOS可以在没有GPS的情况下确定位置,并在到达特定位置/区域时将应用程序“未终止”转换为后台模式(如答案中所示)。从后台,您可以打开GPS并检查更准确的位置信息,以及发送本地推送通知。 - gavdotnet
位置服务和 GPS 在 plist 文件的 UIBackgroundModes 中是否不同?你能为我澄清一下吗? - Muruganandham K
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接