在iOS Swift中,当应用程序处于后台时,如何通过MQTT客户端框架发布或发送消息



我正在开发一个应用程序,通过MQTT客户端框架每15分钟发送一次当前用户位置。当应用程序处于前台时,它工作良好,但当应用程序位于后台时,MQTT委托函数";messageDelivered";不会被称为

我们希望使用MQTT客户端框架在iOS swift中在后台发布消息。

import UIKit
import MQTTClient
class MainViewController: UIViewController {

let MQTT_HOST = "next.nanolink.com" // or IP address e.g. "192.168.0.194"
//let MQTT_HOST = "tnclicks.free.beeceptor.com" // or IP address e.g. "192.168.0.194"
let MQTT_PORT: UInt32 = 1883

private var transport = MQTTCFSocketTransport()
fileprivate var session = MQTTSession()
fileprivate var completion: (()->())?

override func viewDidLoad() {
super.viewDidLoad()


//notification observer
NotificationCenter.default.addObserver(self, selector: #selector(onDidReceiveData(_:)), name: .didReceiveData, object: nil)

//MQTT
self.session?.delegate = self
self.transport.host = MQTT_HOST
self.transport.port = MQTT_PORT
session?.transport = transport

updateUI(for: self.session?.status ?? .created)
session?.connect() { error in
print("connection completed with status (String(describing: error?.localizedDescription))")
if error != nil {
self.updateUI(for: self.session?.status ?? .created)
} else {
self.updateUI(for: self.session?.status ?? .error)
}
}

}

private func subscribe() {
self.session?.subscribe(toTopic: "test/message", at: .exactlyOnce) { error, result in
print("subscribe result error (String(describing: error)) result (result!)")
}
}

private func updateUI(for clientStatus: MQTTSessionStatus) {
DispatchQueue.main.async {
switch clientStatus {
case .connected:
print("Connected")
self.publishMessage("on", onTopic: "test/message")
case .connecting,
.created:
print ("Trying to connect...")
default:
print ("Connetion Failed...")
}
}
}

private func publishMessage(_ message: String, onTopic topic: String)
{
session?.publishData(message.data(using: .utf8, allowLossyConversion: false), onTopic: topic, retain: false, qos: .exactlyOnce)
}

@objc func onDidReceiveData(_ notification:Notification) {
print("check return")

guard session?.status == .connected else {
self.updateUI(for: self.session?.status ?? .error)
return
}

let obj  =  notification.object! as! NSMutableDictionary

print(notification.object!)
let notificationLatitude = obj.value(forKey: "latitude")!
let notificationLongitude = obj.value(forKey: "longitude")!

//let notificationLongitude = notification.object
//        print(" Saved latitude:", latitude!)
//        print(" Saved longitude:", longitude!)

print(" notification latitude:", notificationLatitude)
print(" notification longitude:", notificationLongitude)

guard session?.status == .connected else {
return
}
publishMessage("on", onTopic: "test/message")
}

}

extension MainViewController: MQTTSessionManagerDelegate, MQTTSessionDelegate {
func newMessage(_ session: MQTTSession!, data: Data!, onTopic topic: String!, qos: MQTTQosLevel, retained: Bool, mid: UInt32) {
if let msg = String(data: data, encoding: .utf8) {
print("topic (topic!), msg (msg)")
}
}
func messageDelivered(_ session: MQTTSession, msgID msgId: UInt16) {
print("delivered")
DispatchQueue.main.async {
self.completion?()
}
}
}

extension Notification.Name {
static let didReceiveData = Notification.Name("didReceiveData")
}

我们已经在后台实现了更新位置,因此使用更新位置更新您的代码以在后台发送消息。

import UIKit
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,CLLocationManagerDelegate {
var window: UIWindow?
var locationManager = CLLocationManager()
var backgroundUpdateTask: UIBackgroundTaskIdentifier!
var bgtimer = Timer()
var latitude: Double = 0.0
var longitude: Double = 0.0
var current_time = NSDate().timeIntervalSince1970
var timer = Timer()
var f = 0
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.doBackgroundTask()
return true
}

func applicationWillResignActive(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
print("Entering foreBackground")
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
print("Entering Background")
// self.doBackgroundTask()
}
func doBackgroundTask() {
DispatchQueue.main.async {
self.beginBackgroundUpdateTask()
self.StartupdateLocation()

self.bgtimer = Timer.scheduledTimer(timeInterval:-1, target: self, selector: #selector(AppDelegate.bgtimer(_:)), userInfo: nil, repeats: true)
RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
RunLoop.current.run()
self.endBackgroundUpdateTask()
}
}
func beginBackgroundUpdateTask() {
self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
self.endBackgroundUpdateTask()
})
}
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
self.backgroundUpdateTask = UIBackgroundTaskInvalid
}
func StartupdateLocation() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error while requesting new coordinates")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
self.latitude = locValue.latitude
self.longitude = locValue.longitude
f+=1
print("New Coordinates: (f) ")
print(self.latitude)
print(self.longitude)
}
@objc func bgtimer(_ timer:Timer!){
sleep(2)
/*  if UIApplication.shared.applicationState == .active {
timer.invalidate()
}*/
self.updateLocation()
}
func updateLocation() {
self.locationManager.startUpdatingLocation()
self.locationManager.stopUpdatingLocation()
}}

最新更新