我创建了一个iOS
应用程序,该应用程序在用户登录后仅将Location Coordinates
发送到服务器。我还实现了小部件,该部件将获取在小部件屏幕上显示的位置的快照并将其发送到服务器。该应用程序很简单。我只想在20-30分钟后在后台短暂打开应用程序或小部件,然后将位置发送到服务器。
为此,我已经在应用程序中实现了后台提取。从调试器进行仿真时,它正在工作。但无法在实际的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)
}
}