Hi,
we work fo a company selling refrigeration apparatus around the region. In the guarantee, we offer fast repair times with traveling repairpersons.
So we are building an app to be used by the company repair servicepeople around the region. The company need to be able to know who is the serviceperson nearest to the faulty apparatus, and send them to fix the apapratus.
Every person has (will have) an iOS app and will agree to have Location Updates Always or When In Use, so this is not an issue. Once they will have launched the app once, and agreed to the locaiton policy, the app will stay sleeping most of the times, obviously.
Once the company receives a repair request, we plan to query every serviceperson and decide the nearest. SInce we don't want to be heavy on the battery requirement, we would like (ideally) to query the location only when needed.
Our idea was to send a silent push notification when needed, then the app will awake in background, get a location fix, and call a backend server sending the position. After some seconds we expect to have most o f the locations on DB and we could start deciding which serviceperson to alert, with a proper notification on the app.
We have set up a basic app in XCode 9beta6 and iOS 11 beta (we work for the next release obiously since the app will go live after iOS11 release) that seems to work, but.. but actually only works when connected to XCode.
We have put all the relevant plist and entitlements, but as soon as we disconnect the device from XCode (unpliug the cable) we don't seem to receive any notification (or maybe we receive it but no data is written to our server?).
Silent push notifications are like this:
{"aps":{ "content-available":1}}
Then our app delegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
}
application.registerForRemoteNotifications()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
let bgTask = bgManager()
bgTask.registerBackgroundTask()
locationManager.requestLocation()
let delayInSeconds = 18.0
DispatchQueue.main.asyncAfter(deadline: .now() + delayInSeconds) {
print("locationManager.updated")
bgTask.endBackgroundTask()
completionHandler(.newData)
}
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation])
{
print("DidUpdateLocation ",locations)
locationManager.stopUpdatingLocation()
let todoEndpoint: String = "http://......./apiserver to store coordinates"
guard let url = URL(string: todoEndpoint) else {
print("Error: cannot create URL")
return
}
let urlRequest = URLRequest(url: url)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest) { (data, urlResponse, error) in
/
if(data != nil){
print("data Returned JSON ",data as Any, data?.hexEncodedString() as Any)
if let returnData = String(data: data!, encoding: .utf8) {
print("JSON:", returnData)
DispatchQueue.main.async {
self.logDelegate?.logMessage("HTTP call made and Json received OK")
}
} else {
print(" not converted")
}
}
}
task.resume()
}
The BGManager it's a simple class, found Googlgin on SO, to simulate a background task, hopefully allowing iOS to get a fix for the location. We have added it hoping it would improve things
class bgManager:NSObject{
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
override init(){
super.init()
}
func registerBackgroundTask() {
backgroundTask = UIApplication.shared.beginBackgroundTask {
[unowned self] in
self.endBackgroundTask()
}
}
func endBackgroundTask() {
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
print("End bg task")
}
}
Anyway, any idea why it does not seem to work when we deploy and use the device off XCode? or it if deoes work it is random?
Thanks
Z