Background Fetch не работает на реальном устройстве iOS? - PullRequest
0 голосов
/ 13 апреля 2019

Я создал приложение iOS, которое просто отправляет Location Coordinates на сервер после входа пользователя в систему. Я также реализовал виджет, который делает снимок местоположения, отображает его на экране виджета и отправляет его на сервер. Приложение простое. Я просто хочу через 20-30 минут открыть приложение или виджет на короткое время в фоновом режиме и отправить местоположение на сервер.

Для этого я реализовал в приложении Background Fetch. Работает во время симуляции от отладчика. Но не будет работать на реальном iOS устройстве. Код приложения ниже.

Если есть какое-либо другое решение для выполнения такой задачи, сообщите мне, кроме Push/Remote Notifications. Спасибо

AppDelegate.swift

import UIKit
import UserNotifications
import Alamofire
import CoreLocation

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,  CLLocationManagerDelegate {

    var window: UIWindow?
    var myLat:Double = 0.0
    var myLong:Double = 0.0
    let locationManager = CLLocationManager()
    var MSISDN = ""

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        UIApplication.shared.setMinimumBackgroundFetchInterval(
            UIApplication.backgroundFetchIntervalMinimum)

        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.delegate = self as? CLLocationManagerDelegate
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()

        return true
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        let locValue:CLLocationCoordinate2D = manager.location!.coordinate
        myLat =  locValue.latitude
        myLong = locValue.longitude
        print(locValue)

    }

    func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

        if let userDefaults = UserDefaults(suiteName: "group.com.demo.spoton") {
            var value1 = userDefaults.bool(forKey: "IsLogin")
            if value1 == true {
                print (value1)
                MSISDN = userDefaults.string(forKey: "MSISDN")!

                var fetchResult: UIBackgroundFetchResult!

                print("i'm executing a task")
                let Type = 2
                let root = "https://demourl.com/locreciver.php?latitude="
                let url = "\(root)\(myLat)&longitude=\(myLong)&type=\(2)&msisdn=\(MSISDN)&battery=\(1)";

                Alamofire.request(url, method:.post).responseString {
                    response in
                    switch response.result {
                    case .success:
                        print(response)
                        completionHandler(.newData)

                    case .failure(let error):
                        print(error)
                        completionHandler(.failed)
                    }
                }

                return
            }
            else{
                print("notLogin")
            }
        }


    }// fecth function

    func applicationWillResignActive(_ application: UIApplication) {

    }


    func applicationDidEnterBackground(_ application: UIApplication) {
    }

    func applicationWillEnterForeground(_ application: UIApplication) {

    }

    func applicationDidBecomeActive(_ application: UIApplication) {
    }

    func applicationWillTerminate(_ application: UIApplication) {

    }
}

// TodayViewController.swift // Виджет

import UIKit
import NotificationCenter
import CoreLocation
import Alamofire
import Swift
import GoogleMaps
import MapKit

class TodayViewController: UIViewController, NCWidgetProviding, CLLocationManagerDelegate,MKMapViewDelegate {
    @IBOutlet weak var lblTitle: UILabel!

    @IBOutlet weak var mapImage: UIImageView!

    let locationManager = CLLocationManager()
    var myLat:Double = 0.0
    var myLong:Double = 0.0
    var MSISDN = ""


    @objc func doLaunchApp(){
        if let url = NSURL(string: "mainAppUrl://"){
            self.extensionContext?.open(url as URL, completionHandler: nil)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        //        self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded
        //        let url = URL(string: "mainAppUrl://")!
        //        self.extensionContext?.open(url, completionHandler: { (success) in
        //            if (!success) {
        //                print("error: failed to open app from Today Extension")
        //            }
        //        })
        //


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(TodayViewController.doLaunchApp))

        self.view.addGestureRecognizer(tapGesture)



        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()



    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        let locValue:CLLocationCoordinate2D = manager.location!.coordinate
        myLat =  locValue.latitude
        myLong = locValue.longitude


    }


    func SendData(){
        print("Sent")
        takeShot()
        var batteryLevel:Float = UIDevice.current.batteryLevel
        let Type = 2
        let root = "https://demourl.com/locreciver.php?latitude="
        let url = "\(root)\(myLat)&longitude=\(myLong)&type=\(Type)&msisdn=\(MSISDN)&battery=\(batteryLevel)";

        Alamofire.request(url, method:.post).responseString {
            response in
            switch response.result {
            case .success:
                print(response)
            case .failure(let error):
                print(error)
            }
        }


    }

    func takeShot(){
        let mapSnapshotOptions = MKMapSnapshotter.Options()

        // Set the region of the map that is rendered.
        let location = CLLocationCoordinate2DMake(myLat, myLong) // Apple HQ
        let region = MKCoordinateRegion(center: location, latitudinalMeters: 900, longitudinalMeters: 900)


        mapSnapshotOptions.region = region

        // Set the scale of the image. We'll just use the scale of the current device, which is 2x scale on Retina screens.
        mapSnapshotOptions.scale = UIScreen.main.scale

        // Set the size of the image output.
        mapSnapshotOptions.size = CGSize(width: mapImage.frame.width, height: mapImage.frame.height)

        // Show buildings and Points of Interest on the snapshot
        mapSnapshotOptions.showsBuildings = true
        mapSnapshotOptions.showsPointsOfInterest = true

        let snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)

        snapShotter.start { (snapshot:MKMapSnapshotter.Snapshot?, NSError) in
            let image = snapshot?.image

            var annotation = MKPointAnnotation()
            annotation.coordinate = CLLocationCoordinate2D(latitude: self.myLat, longitude: self.myLong)

            annotation.title = "Your Title"

            let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "annotation")
            let pinImage = UIImage(named: "pin")
            print(pinImage)
            UIGraphicsBeginImageContextWithOptions(image!.size, true, image!.scale);

            image?.draw(at: CGPoint(x: 0, y: 0)) //map

            pinImage!.draw(at: (snapshot?.point(for: annotation.coordinate))!)

            annotationView.drawHierarchy(in: CGRect(x: snapshot!.point(for: annotation.coordinate).x, y: (snapshot?.point(for: annotation.coordinate).y)!, width: annotationView.frame.size.width-100, height: annotationView.frame.size.height-100), afterScreenUpdates: true)


            let finalImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            //            completion(image: finalImage, error: nil)



            self.mapImage.image = finalImage
            //self.mapImage.image = snapshot?.image
        }
    }


    func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
        if let userDefaults = UserDefaults(suiteName: "group.com.demo.spoton") {
            var value1 = userDefaults.bool(forKey: "IsLogin")
            if value1 == true {
                print (value1)
                MSISDN = userDefaults.string(forKey: "MSISDN")!

                lblTitle.text = "Service Active"
                let timer1 = Timer.scheduledTimer(withTimeInterval: 1500.0, repeats: false) { (timer) in
                    self.SendData()
                }

                let timer2 = Timer.scheduledTimer(withTimeInterval: 1500.0, repeats: true) { (timer) in
                    print("Looop")
                    self.SendData()
                }



            }
            else {
                lblTitle.text = "SpotOn Service InActive. Needs Login"

            }



        }

        completionHandler(NCUpdateResult.newData)
    }

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...