后台保活有各种各样的方案,我采用的是后台定位方法,根据自己的APP类型自己选择吧。
直接进入主题:
-
引入
#import <CoreLocation/CoreLocation.h>
框架 -
在
plist
文件中添加定位所需的隐私权限Privacy - Location Always and When In Use Usage Description
和Privacy - Location When In Use Usage Description
-
开启后台模式
1571993330762.jpg
-
在前台打开定位,同时开启了一个后台计时器任务
下面直接附上AppDelegate
的代码
#import "AppDelegate.h"
#import <CoreLocation/CoreLocation.h>
#import <UserNotifications/UserNotifications.h>
@interface AppDelegate () <CLLocationManagerDelegate>
@property (nonatomic) dispatch_source_t badgeTimer;
@property(nonatomic, strong) CLLocationManager *appleLocationManager;
@property(nonatomic, strong) CLBeaconRegion *beaconRegion;
@property(nonatomic, assign) __block UIBackgroundTaskIdentifier bgTask;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 写日志到本地文件,可以将控制台输出直接写入本地沙盒路径
[self redirectNSlogToDocumentFolder];
//注册推送
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!error) {
NSLog(@"request authorization succeeded!");
}
}];
// 启动就直接开启定位
[self startLocation];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[self stratBadgeNumberCount];
[self startBgTask];
}
- (void)startLocation {
self.appleLocationManager = [[CLLocationManager alloc] init];
self.appleLocationManager.allowsBackgroundLocationUpdates = YES;
if (@available(iOS 11.0, *)) {
self.appleLocationManager.showsBackgroundLocationIndicator = YES;
}
self.appleLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.appleLocationManager.distanceFilter = kCLDistanceFilterNone;
self.appleLocationManager.delegate = self;
[self.appleLocationManager requestAlwaysAuthorization];
self.appleLocationManager.pausesLocationUpdatesAutomatically = NO;
[self.appleLocationManager startUpdatingLocation];
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"FDA50693-A4E2-4FB1-AFCF-C6EB07647825"];
if (@available(iOS 13.0, *)) {
_beaconRegion = [[CLBeaconRegion alloc] initWithUUID:uuid identifier:@"beacon"];
} else {
_beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"beacon"];
}
_beaconRegion.notifyEntryStateOnDisplay = YES;
_beaconRegion.notifyOnEntry = YES;
[self.appleLocationManager startRangingBeaconsInRegion:self.beaconRegion];
// [self.appleLocationManager startMonitoringForRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region {
// for (CLBeacon *beacon in beacons) {
// NSLog(@"\nUUID: %@\nMajor:%ld\nminor:%ld\n精度:%.4f\nrssi:%ld", beacon.proximityUUID.UUIDString, (long)beacon.major.integerValue, (long)beacon.minor.integerValue, beacon.accuracy, (long)beacon.rssi);
// }
NSLog(@"扫描到beacon");
}
- (void)startBgTask{
UIApplication *application = [UIApplication sharedApplication];
self.bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
//这里延迟的系统时间结束
[application endBackgroundTask:self.bgTask];
NSLog(@"%f",application.backgroundTimeRemaining);
}];
}
- (void)stratBadgeNumberCount{
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
_badgeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(_badgeTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(_badgeTimer, ^{
[UIApplication sharedApplication].applicationIconBadgeNumber++;
//如果系统给的剩余时间小于60秒 就终止当前的后台任务,再重新初始化一个后台任务,重新让系统分配时间,这样一直循环下去,保持APP在后台一直处于active状态。
if ([UIApplication sharedApplication].backgroundTimeRemaining < 60) {
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
self.bgTask = UIBackgroundTaskInvalid;
}];
}
});
dispatch_resume(_badgeTimer);
}
/** 苹果_用户位置更新后,会调用此函数 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
// [self.appleLocationManager stopUpdatingLocation];
// self.appleLocationManager.delegate = nil;
// [self.appleLocationManager startMonitoringForRegion:self.beaconRegion];
[manager startRangingBeaconsInRegion:self.beaconRegion];
NSLog(@"success");
}
/** 苹果_定位失败后,会调用此函数 */
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
// [self.appleLocationManager stopUpdatingLocation];
// self.appleLocationManager.delegate = nil;
NSLog(@"error");
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#pragma mark - 日志收集
- (void)redirectNSlogToDocumentFolder
{
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSDateFormatter *dateformat = [[NSDateFormatter alloc]init];
[dateformat setDateFormat:@"yyyy-MM-dd-HH-mm-ss"];
NSString *fileName = [NSString stringWithFormat:@"LOG-%@.txt",[dateformat stringFromDate:[NSDate date]]];
NSString *logFilePath = [documentDirectory stringByAppendingPathComponent:fileName];
// 先删除已经存在的文件
NSFileManager *defaultManager = [NSFileManager defaultManager];
[defaultManager removeItemAtPath:logFilePath error:nil];
// 将log输入到文件
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
}
@end
网友评论