iOS中的地理围栏当App关闭/杀死时 [英] Geofencing in iOS When App is closed / Killed

查看:272
本文介绍了iOS中的地理围栏当App关闭/杀死时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Geofencing,我想触发didEnterRegiondidExitRegion当应用处于前台或处于后台状态时,它正在工作。但我想在应用程序处于非活动状态时触发它。我的代码如下:

I am working on Geofencing and I want to trigger "didEnterRegion" and "didExitRegion" it is working when the app is in foreground or in background state. But I want to trigger it when the app is inactive state also. My code is follows:

GeofencingClass.h

#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

@interface GeofencingClass : NSObject <UIWebViewDelegate,UIGestureRecognizerDelegate,CLLocationManagerDelegate> {

CLLocationManager *locationManager;
   NSMutableArray *geofences;
}
@property (strong, nonatomic) NSMutableArray *geofences;
@property (nonatomic,retain)CLLocationManager *locationManager;
+(void)GeofencingCoordinatesFromAPI;
+(void)StartGeoFencingWithGeoData:(NSMutableArray *)GeoDataArray;
@end

GeofencingClass.m

    #import "GeofencingClass.h"

    @implementation GeofencingClass
    @synthesize locationManager,geofences;

    +(void)GeofencingCoordinatesFromAPI {

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

        NSInteger Parameter1 = [userDefaults integerForKey:@"Parameter1"];
        NSString* Parameter2 = [userDefaults objectForKey:@"Parameter2"];
        NSString* secretAgent = [userDefaults objectForKey:@"nv_secretAgent"];

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
            NSError *error = nil;
            NSString *urlstring = [NSString stringWithFormat:@"https://geofencingapiurl.com?parm1=%ld&parm2=%@&device=ios", (long)Parameter1, Parameter2];
            urlstring = [urlstring stringByReplacingOccurrencesOfString:@"(null)" withString:@""];
        urlstring= [urlstring stringByAddingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding];
            NSURL *url = [NSURL URLWithString:urlstring];
            NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
            [request setValue:secretAgent forHTTPHeaderField:@"User-Agent"];
            NSURLResponse* response = nil;
            NSData* jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
            if(!error) {
                //NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
                NSMutableDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];

                if ([jsonDict objectForKey:@"Authentication"] && [@"success" isEqualToString:[jsonDict objectForKey:@"Authentication"]]) {
                    geofences = [[jsonDict valueForKey:@"geodata"] mutableCopy];




                    dispatch_async(dispatch_get_main_queue(), ^{

                    [self StartGeoFencingWithGeoData:geofences];
                    });





                } else {
                    NSLog(@"Invalid authentication");
                }
            }
        });
    }

    +(void)StartGeoFencingWithGeoData:(NSMutableArray *)GeoDataArray {

        locationManager = [[CLLocationManager alloc]init];
       // NSLog(@"GeoDataArray = %@",GeoDataArray);
        if(IS_OS_8_OR_LATER) {
            [locationManager requestWhenInUseAuthorization];
            [locationManager requestAlwaysAuthorization];
        }

        locationManager.delegate = self;
        [locationManager startUpdatingLocation];
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
        locationManager.distanceFilter = kCLLocationAccuracyBest;
        NSLog(@"latitude: %f   longitude: %f",locationManager.location.coordinate.latitude,locationManager.location.coordinate.longitude);
        NSLog(@"speed: %f  altitude: %f",locationManager.location.speed,locationManager.location.altitude);

        for (int i = 0; i < [GeoDataArray count]; i++) {
            CLLocationDegrees geo_latitude = [[[GeoDataArray objectAtIndex:i] valueForKey:@"geo_lattitude"] floatValue];
            CLLocationDegrees geo_longitude = [[[GeoDataArray objectAtIndex:i] valueForKey:@"geo_longitude"] floatValue];

            float Radius  = [[[GeoDataArray objectAtIndex:i] valueForKey:@"geo_radius"] floatValue];
            CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(geo_latitude, geo_longitude);

            CLCircularRegion *region = [[CLCircularRegion alloc]initWithCenter:coordinate radius:Radius identifier:[[GeoDataArray objectAtIndex:i] valueForKey:@"geo_id"]];
            [locationManager startMonitoringForRegion:region];
        }
    }
    -(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {

        NSLog(@"Region Monitoring has been started%@",region.identifier);
        [locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:2];
    }
    -(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
        NSLog(@"Entered in some Region %@",region.identifier);
        for (int i= 0; i <[GeoData count]; i++) {

            NSInteger geo_id =[[[GeoData objectAtIndex:i] valueForKey:@"geo_id"] integerValue];

            if ([region.identifier integerValue] == geo_id) {
                NSInteger geo_action = [[[GeoData objectAtIndex:i] valueForKey:@"geo_action"] integerValue];
                if (geo_action == 0) {
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];
        localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:2];
      localNotification.alertBody = @"You are now Entered in a region";
        localNotification.timeZone = [NSTimeZone defaultTimeZone];
        localNotification.soundName = UILocalNotificationDefaultSoundName;
        NSMutableDictionary *userData = [[GeoData objectAtIndex:i] mutableCopy];
        localNotification.userInfo = userData;
     [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];  
                }
            }
        }
    }

    -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
        NSLog(@"Exit from some Region %@",region.identifier);
        for (int i= 0; i <[GeoData count]; i++) {

            NSInteger geo_id =[[[GeoData objectAtIndex:i] valueForKey:@"geo_id"] integerValue];

            if ([region.identifier integerValue] == geo_id) {
                NSInteger geo_action = [[[GeoData objectAtIndex:i] valueForKey:@"geo_action"] integerValue];
                if (geo_action == 1) {
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];
        localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:2];
      localNotification.alertBody = @"You are now Exit from region";
        localNotification.timeZone = [NSTimeZone defaultTimeZone];
        localNotification.soundName = UILocalNotificationDefaultSoundName;
        NSMutableDictionary *userData = [[GeoData objectAtIndex:i] mutableCopy];
        localNotification.userInfo = userData;
     [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
                }
            }
        }
    }
    -(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {

        if (state == CLRegionStateInside){

            [self AlreadyInsideRegion:region];

        } else if (state == CLRegionStateOutside){

            [self NotInRegion:region];

        } else if (state == CLRegionStateUnknown){
            NSLog(@"Unknown state for geofence: %@", region);
            return;
        }
    }
    - (void)AlreadyInsideRegion:(CLRegion *)region {
        NSLog(@"Already in a Region");
    }

    - (void)NotInRegion:(CLRegion *)region {
        NSLog(@"You are Outside from a Region");

    }
    @end

MYAppDelegate.h

#import <UIKit/UIKit.h>

@interface MYAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

MyAppDelegate.m

#import "MYAppDelegate.h"
#import "GeofencingClass.h"

@interface MYAppDelegate ()
@end

@implementation MYAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
        [GeofencingClass GeofencingCoordinatesFromAPI];
    }
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
}

- (void)applicationDidEnterBackground:(UIApplication *)application {

}

- (void)applicationWillEnterForeground:(UIApplication *)application {

}

- (void)applicationDidBecomeActive:(UIApplication *)application {

[GeofencingClass GeofencingCoordinatesFromAPI];
}

- (void)applicationWillTerminate:(UIApplication *)application {

}

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

/// Handled Deeplinking here 
    return YES;
}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
 /// Registered Push Notification Here and it is working fine
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"Error:%@",error);
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    /// Handled received Push Notification Here and it is working fine
}

-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    ///Handled received local push Notification Here and it is working fine
}

如果应用程序处于后台或前台,但上面的代码工作正常,但如果我双击主页按钮并从任务中关闭应用程序然后地理围栏无法正常工作可以帮助我实现这一目标。

The above code is working fine if the app is in background or foreground but if i double tap on Home Button and close the app from task then geofencing not working can anybody help me to achieve this goal.

注意:我正在使用XCode 7.3.1和iOS 9.3而我在iPhone 5s上测试它。

Note: I am using XCode 7.3.1 and iOS 9.3 while I am testing this on iPhone 5s.

提前致谢!!!!!

推荐答案

很抱歉,但有点不同:
(ADC网站)

Sorry but is a bit different: (ADC SITE)


如果您让重要更改位置服务运行并且您的
iOS应用随后被暂停或终止,则服务
会在新位置时自动唤醒您的应用数据到了。在
的唤醒时间,应用程序被置于后台,您将获得
的少量时间(大约10秒)来手动重启位置
服务并处理位置数据。 (您必须在任何待处理位置
更新之前在后台手动重启
位置服务,如了解何时启动
位置服务中所述。)

If you leave the significant-change location service running and your iOS app is subsequently suspended or terminated, the service automatically wakes up your app when new location data arrives. At wake-up time, the app is put into the background and you are given a small amount of time (around 10 seconds) to manually restart location services and process the location data. (You must manually restart location services in the background before any pending location updates can be delivered, as described in Knowing When to Start Location Services.)

所以iOS会唤醒你的应用但你必须:
1)实例化一个新的CLLocationManager
2)等待'直到第一次回叫使用geoloc

So iOS will awake your app BUT you must: 1) instantiate a NEW CLLocationManager 2) wait 'till first call back to use geoloc

注意ADC状态,您将在后台运行,因此或示例如果您需要用户将其放在前台,请使用本地通知。

notes ADC states, you will be running in background, so or example use local notification if You need the user put it in foreground.

这篇关于iOS中的地理围栏当App关闭/杀死时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆