Issue
I Switched to push notifications, check my answer below.
I'm trying to implement a function that runs in the background when the app is put in the background. The implementation is similar to a timer that has to keep running when we exit the app. I already activated "Background Processing" in my app and this is the function I want to run in the background:
public func keepCheck(timer:Timer) {
DispatchQueue.global(qos: DispatchQoS.background.qosClass).async {
print("do some background task")
if self.check == true {
if self.outBool == false {
self.residualWaterWeight -= self.indoorDryRate
if self.residualWaterWeight <= 0.0 {
self.appDelegate?.scheduleNotification(notificationType: "Your Clothes are Dry!",body: "I Love fabric conditioner smell in the morning <3")
self.defaults.set(false, forKey: "keep_check")
}
print(self.residualWaterWeight)
} else {
self.do10min()
}
self.check = self.defaults.bool(forKey: "keep_check")
}
DispatchQueue.main.async {
print("update some UI")
}
}
}
Now this function runs in the background when the app is open but it stop when you tap the home button. How can I prevent this function from stopping on app pause?
Solution
I switched from local notifications to push notifications setting my remote flask application to handle all the background processing and notification sending with firebase:
Set your app up to receive push notifications
Create a flask application on your remote server and deploy it. Here are some sample instructions to create and deploy your flask application
Configure flask with your Firebase as a server
DISCLAIMER: you should't proceed if you haven't follow successfully the previous steps.
Now if you are new to Flask, it handle HTTP requests pretty neatly and it's very intuitive.
4.1. Open your Flask application file for editing
4.2 Add
import requests
andfrom pyfcm import FCMNotification
in your imports and this right after the imports:push_service = FCMNotification(api_key=SERVER_KEY)
whereSERVER_KEY
is your server key from firebase in your project settings.4.3 Add the following code (every bit of this code in ALL CAPS is something you can change):
@app.route('/MY_REQUEST_NAME') def MY_FUNCTION(): # MY_ARGUMENT in this case will be the iOS device token MY_ARGUMENT = str(request.args.get('MY_ARGUMENT')) # do calculations result = push_service.notify_single_device( registration_id=MY_ARGUMENT, message_title=MESSAGE, message_body=BODY ) return MY_RESULTS # if your goal is just sending notification you don't really need a return statement
4.4 Activate your virtual environment
source myprojectenv/bin/activate
and typepip install requests pyfcm
The Flask application will trigger the function we just wrote when you type in your browser:https://example.com/my_request_name?my_argument=my_argument_value
or you can use your server public IP address instead of the domain if you don't have one.Go to your
AppDelegate
and modify the following function to store the device fcm_token somewhere. I personally used thedefaults.standard
:func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { print("Firebase registration token: \(fcmToken)") // Save Token: UserDefaults.standard.set(fcmToken, forKey: "FCM_TOKEN") NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict) // TODO: If necessary send token to application server. // Note: This callback is fired at each app startup and whenever a new token is generated. }
Finally, in Xcode you can call your request like this:
let token = UserDefaults.standard.string(forKey: "FCM_TOKEN")! let url : URL = URL(string: "https://example.com/my_request_name?my_argument=\(token)")! let task = URLSession.shared.dataTask(with: url) task.resume()
Answered By - Fabio Magarelli
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.