背景
有一次老板提出了這種需求:我們的監(jiān)控App必須能一直在后臺運行并且殺死了也能自動重啟!然后淚流滿面的iOS開發(fā)只能默默的尋找解決辦法。。。別說,還真有!
iOS系統(tǒng)常駐后臺的幾種辦法
在XCode項目的Capabilities選項中,有這么幾種后臺運行模式的權(quán)限:

大概就是音頻、定位、藍牙、遠程通知等等,還有具有voip能力的應(yīng)用可以通過在系統(tǒng)注冊socket連接來實現(xiàn)后臺喚醒。
Note:需要注意的是這些能力必須匹配App的功能,如果App中沒有合理的使用理由的話上架會被拒絕的。
因為開發(fā)的是一款監(jiān)控位置的軟件,所以我在這里只寫一下后臺位置權(quán)限的使用。
實現(xiàn)方法
1、勾選Location updates
首先需要吧Capabilities配置里的Location updates選項勾上,不然是沒有定位權(quán)限的。
2、添加CoreLocation.framework
定位功能是CoreLocation里的,需要先引入這個framework
3、在Info.plist里添加定位權(quán)限描述文字
需要添加這2條描述文字:
Privacy - Location Always Usage Description - 持續(xù)的后臺定位
Privacy - Location When In Use Usage Description - 使用中定位
iOS11還需要再添加這一條
Privacy - Location Always and When In Use Usage Description - 定位權(quán)限選擇說明
Note:這里在iOS11有了變化,如果要使用始終定位權(quán)限,強制要求也必須給用戶選擇使用中定位的選項。
如果選擇了使用中定位的權(quán)限,App如果在后臺繼續(xù)定位就會在頂部顯示正在使用定位的藍條,這樣就避免了App偷偷的在后臺定位。
4、創(chuàng)建并配置CLLocationManager
CLLocationManager的各項參數(shù)配置就不詳細說了,根據(jù)需求設(shè)置即可。重點說一下啟動持續(xù)定位的方法。
5、開啟持續(xù)精確定位
iOS9以上需要在開啟定位前調(diào)用一下這兩個方法(9以下只需要調(diào)用第二個),用戶就會彈出定位權(quán)限申請
[locationManager setAllowsBackgroundLocationUpdates:YES];
[locationManager requestAlwaysAuthorization]
然后開啟定位時調(diào)用下面的方法就可以在didUpdateLocations接受定位信息了
[locationManager startUpdatingLocation]
Tips:檢測定位權(quán)限開啟可以在didFailWithError回調(diào)中接收到響應(yīng),返回的error的code是kCLErrorDenied類型的,就是未開啟定位權(quán)限。
低電量模式有時候可能會影響到后臺定位,可以通過
[[NSProcessInfo processInfo] isLowPowerModeEnabled] (iOS9以上)來判斷。
經(jīng)過實際使用,基本上開啟持續(xù)精確定位以后,后臺可以一直存活。
不過到夜里會有比較大的概率被系統(tǒng)kill掉。
重度使用其他軟件導致系統(tǒng)資源緊張,也可能會被系統(tǒng)kill掉。
還有如果未開啟4G網(wǎng)絡(luò)通話功能打電話或者關(guān)閉4G信號并在室內(nèi)導致定位失敗時間較長,也可能會被kill掉。
用戶主動在多任務(wù)進程里關(guān)掉App,也會停止定位。
重點來了,如何支持被kill掉以后能夠后臺自動重啟
CLLocationManager還有一個持續(xù)定位的方法
startMonitoringSignificantLocationChanges
這個是粗略定位,只有在4G基站切換的時候才會響應(yīng)didUpdateLocations回調(diào)。本來這個是用在不需要那么精確定位的場景下省電開啟的。
那這個方法有什么特殊的呢,那就是支持后臺自動喚醒!而且可以和startUpdatingLocation同時開啟!
Note:這個基站定位只有在移動超過一定距離的時候,才會有響應(yīng),大概最少也得1公里的樣子,所以也不是實時就能喚醒的,但是通過定位能力也只能做到這里了??
使用方法:
在調(diào)用[locationManager startUpdatingLocation]的時候,也調(diào)用一下
[locationManager startMonitoringSignificantLocationChanges]
然后只需要在AppDelegate里的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
回調(diào)中加入下邊的代碼,就可以了。
/*********應(yīng)用kill以后基站定位喚醒*************/
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
NSLog(@"在后臺被喚醒");
// do something,這里就可以再次調(diào)用startUpdatingLocation,開啟精確定位啦
}
當然了,用戶必須選擇了始終定位權(quán)限,才可能從后臺自動啟動,這也是為了保護用戶隱私權(quán)和節(jié)省電力,不想被偷偷監(jiān)控的,把所有軟件定位權(quán)限都設(shè)置成使用時就可以了,因為iOS11強制App必須有這個選項,所以抓緊升級iOS11吧 ??。