Flutter: iOS notification background handler - flutter

How to handle iOS background notification click_action when it is null ?
{
"to" : "abcd1234",
"collapse_key" : "type_a",
"notification" : {
"title": "Testing",
"body" : "Testing 1 2 3 4 5 6 7"
},
"data" : {
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"route": "/Home",
}
}
onBackgroundMessage: Platform.isAndroid ? BackgroundHandler.backgroundHandler : null
This post mentioned onBackgroundMessage not implemented in iOS just use for android. Is there a way to handle in iOS ? Thanks.

Yes.
If you did all the ios firebase configurations using XCode, you can use the native swift functions to listen to the background notifications on iOS.
Inside your AppDelegate class,
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
/// Here you will get the silent background notification .
/// May be you can call you flutter code from here if you need.
/// Make sure that you end your processing quickly, else you will not get the background notification regularly and timely from iOS.
/// After you completed, make sure you call the completionHandler so that iOS knows you are done with your background task and you completed it so quickly.
completionHandler(UIBackgroundFetchResult.newData)
}
FlutterFire team is working on this to bring to the flutter side and you can expect this very soon I think by looking at their GitHub PRs.

Related

How do you receive APNS payload data from a Silent Notification?

I'm testing notifications in XCode 12.2. It is very easy to test alert style notifications. You just drag them onto your app in simulator and the payload shows up in:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
notificationsDispatcher.process(userInfo)
completionHandler(.newData)
}
Now, when testing silent notifications I can get the silent notification to fire after setting "Background fetch" in background modes. I then get into:
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
debugPrint("hello silence ")
}
This is fine if i want the app to do something unrelated to the data in the payload. How do I see the actual apns payload data?
I'm trying to access this payload example that i'm using:
{
"aps": {
"category": "tasks",
"content-available": 1,
"thread-id": "tasks"
},
"resource": {
"resourceType": null,
"additionalProperties": {
"taskIds": [
"xxx"
],
"classification": "xxx",
"status": "xxx"
}
}
}
Simulating silent push notifications currently does not work if the content-available flag is set since it calls the wrong delegate method.
If you try with an actual device and send a real push notification, it should call the application(:didReceiveRemoteNotification:fetchCompletionHandler:) delegate and you can access the payload.
There are also some forum posts about this, like https://developer.apple.com/forums/thread/652649.

Apple APNS Silent/Background Notification with Alert Content - How to make both works

Hi I'm curious to know if anybody has send a APNS push to your phone with payload like:
{
"aps" : {
"alert" : "New Content.",
"badge" : 9,
"content-available" : 1
},
"acme1" : "bar",
"acme2" : 42 }
}
And get your app to call
application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
successfully but never see a banner / alert on the lock screen
How do you at the same time have it show the alert?
Thanks!

How to implement CallKit in real app?

I am trying to implement Apple CallKit in my VoIP application. I am using Xcode 9.2, Swift 4.0.3, iOS 10.3. Problem is I do not know how exactly to do this. I have tried to search for tutorial in Web, but I failed to find tutorial based on real system. They all using fake systems, only simulate calls! I have a class which rules with someone third person library which is responsible for the calls. So, if I have incoming call happens, some event goes through observer. Like this:
NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: Notifications.Name.transMessage.rawValue), object: nil, queue: nil) { notification in
self.handleLibtransEvents()
}
where self.handleLibtransEvents is private function calling calls.
Plus, I have installed working PUSH Notification system in AppDelegate.swift. Like this:
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("NOTIFICATION ERROR: \(error)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let pushToken = deviceToken.reduce("", {$0 + String(format: "%02X", $1)}).lowercased()
print("pushToken: \(pushToken)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if UIApplication.shared.applicationState != UIApplicationState.active {
// PUSH: Incoming call event!
}
}
So there are two places, I can catch incoming call but I have not any idea how to catch real call through Apple CallKit. I will be thankful for any help, advice, call example. Thanks!
P. S. I have installed all settings correctly.
CallKit is basically a framework to show up a Call UI when ever you receive a voip call or make a new call, So it will do nothing if you pass it a number n assume it will make call, Keep it in mind its only to show a UI for receive call & make call.
To make calls n receive calls you will need 3rd party services like Sinch and many other.

watchOS2 app and iPhone app communication

In the watchOS1, we had a method “openParentApplication”. This method communicated with the phone application even when it wasn’t running in foreground or background and fetched a reply immediately. I need something similar for watchOS2. I want my watch application to communicate immediately with the phone app even if my iPhone application is not running. Methods like updateApplicationContext:error:, sendMessage:replyHandler:errorHandler: and transferUserInfo: are not helpful in this scenario.
Please can someone suggest me a better approach to achieve this?
Actually sendMessage:replyHandler:errorHandler: is doing exactly what you are asking for. As long as your watch is connected to your phone it immediately gets a response to the message. This is working when the app is in the foreground, in the background or not running at all.
Here is how you set it up:
In the WatchExtension:
Setup the session. Typically in your ExtensionDelegate:
func applicationDidFinishLaunching() {
if WCSession.isSupported() {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
}
And then send the message when you need something from the app:
if WCSession.defaultSession().reachable {
let messageDict = ["message": "hello iPhone!"]
WCSession.defaultSession().sendMessage(messageDict, replyHandler: { (replyDict) -> Void in
print(replyDict)
}, errorHandler: { (error) -> Void in
print(error)
}
}
In the iPhone App:
Same session setup, but this time also set the delegate:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
...
if WCSession.isSupported() {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
}
And then implement the delegate method to send the reply to the watch:
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
replyHandler(["message": "Hello Watch!"])
}
This works whenever there is a connection between the Watch and the iPhone. If the app is not running, the system starts it in the background. So, basically it just works like openParentApplication(_:reply:)

Get notification when app is in background mode

I want to call a function when I receive a notification, even when my application is in background
I found a lot of question / answer on stackoverflow
but in me it does not. So I will explain everything I 've done
i have background mode activate
here
my info.plist is good
here
in my didFinishLaunchingWithOption i have
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Badge | .Sound | .Alert, categories: nil))
application.registerForRemoteNotifications()
and i have
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
println("NOTIFICATION 4");
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
println("NOTIFICATION FETCH");
}
but i can't see my log when i send my notification
my notification is send like this
{ deviceToken: XXXXX,
expiration: 1442225011,
identifier: 0,
payload:
{ 'content-available': '1',
aps: { badge: 0, alert: 'Hello' } } }
I do not know what to do more ... I really can not receive this notification, nothing happens ( I receive the banner but no call to my function)
thank's a lot
As you can read in documents:
The aps dictionary can also contain the content-available property. The content-available property with a value of 1 lets the remote notification act as a “silent” notification.
so you should insert content-available in aps dictionary, like this:
{ deviceToken: XXXXX,
expiration: 1442225011,
identifier: 0,
payload:
{ aps: { 'content-available': '1', badge: 0, alert: 'Hello' } } }