I am using Google Firebase to send push notifications. For Android client, I only send data (not notification) and if notification required, I send it as local notification and it works fine. Data arrive whether the app is running or killed or in the background. In IOS, I configured APNs with Firebase but I have some trouble about background data and notification. The code below sends background data to IOS client by using APNs. "content_available" flag direct notification to APNs but as Firebase documentation mentioned, APNs are not guaranteed to be delivered. The link below explains it.
https://firebase.google.com/docs/cloud-messaging/http-server-ref
"On iOS, use this field to represent content-available in the APNs payload. When a notification or message is sent and this is set to true, an inactive client app is awoken, and the message is sent through APNs as a silent notification and not through the FCM connection server. Note that silent notifications in APNs are not guaranteed to be delivered, and can depend on factors such as the user turning on Low Power Mode, force quitting the app, etc. On Android, data messages wake the app by default. On Chrome, currently not supported."
If I add the codes at the comment lines, APNs sent always notification whether the app is in foreground, background or killed. Of course, I don't want push notification if the app is in the foreground. Furthermore, if the user doesn't click the notification (click the app icon), the code is not triggered. Is there any way to use APNs as Firebase on Android? In Android background data notification always sent to the client successfully whether the app is in the foreground, background or killed.
private static String apiKey = "AIzaSy............";
public static void sendNotification(JSONObject jsonData, String token) {
try {
JSONObject jsonGCM = new JSONObject();
jsonGCM.put("to", token);
jsonGCM.put("data", jsonData);
jsonGCM.put("content_available", true);
//jsonGCM.put("priority", "high");
/*JSONObject jsonNotification = new JSONObject();
jsonNotification.put("title", "Some Title");
jsonNotification.put("body", "Some body.");
jsonGCM.put("notification", jsonNotification);*/
URL url = new URL(
//"https://gcm-http.googleapis.com/gcm/send");
"https://fcm.googleapis.com/fcm/send");
HttpsURLConnection conn = (HttpsURLConnection) url
.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Type",
"application/json; charset=UTF-8");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "key="
+ apiKey);
OutputStream os = conn.getOutputStream();
os.write(jsonGCM.toString().getBytes("UTF-8"));
os.flush();
InputStream in = new BufferedInputStream(
conn.getInputStream());
System.out.println("Response code -->"
+ conn.getResponseCode());
os.close();
}
catch (Exception e) {
// TODO: handle exception
}
}
Related
I am using flutter to develop my app , firebase auth for user authentication and firebase messaging for data notifications when app is in background and terminated state.
In IOS,
when app does a fresh firebase authentication and generate a fcm token, notifications are received when app is in background state, but once i kill the app from background , and launch it again , the notifications stop being received by the app until i do a firebase auth verification and generate a new fcm token again.
in main.dart file in the main function initializeFirebase function is
called .
Future initializeFirebase() async {
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(
_onAppInTerminatedNotificationHandler, // This Callback must be static
);
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
}
Future<void> _onAppInTerminatedNotificationHandler(
RemoteMessage message,
) async {
//await Firebase.initializeApp();
print('A new terminated Push Notification Received');
await NotificationManager.instance.showLocalNotification(message);
}
in iOS, there will be a pop up that will ask the user to accept or deny push notification permission.
if the user deny the permission or they set to not to display the push notification in the settings, will the FCM listeners to receive FCM message still be called? I mean this lines below.
in Android, if I disable to display the push notification in phone settings, then the listeners below will still be called. but unfortunately I can't test it for iOS since I don't have apple developer account yet at the moment
// to receive foreground message
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
});
// to receive background message
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
}
From Cloud Firestore | Requesting permission (Apple & Web),
On iOS, macOS & web, before FCM payloads can be received on your
device, you must first ask the users permission. Android applications
are not required to request permission.
So you need permission for the listeners to be called on iOS.
I configured my app to work with FCM Data messages, push notifications are coming when the app is in foreground and background state, BUT NOT if the app is terminated (swipe up from multitasking).
As far as I know, if you are using the Data messages you will be in charge of handling the received message and present a notification to the user. Otherwise, if you are using Notification Messages, FCM is handling the message for you and directly displays a notification if the app is in background/closed.
In my app I must use Data messages and therefore have problems with push notifications when app is killed.
From the answers of this post IOS data notifications with FCM, Data messages can't be received in iOS if the app is killed.
I did the following test: I sent a Notification message (instead of Data message) from Firebase Console and the push notification WAS showing up even if the app was closed.
How can I solve the problem in this situation?
Firebase Notification Messages can have an optional data payload. This payload is the same size as Data Messages.
So just use Notification Messages. If the app is killed, your notification will be displayed with the default push notification handler.
If your app is open, you don't have to show the notification, and can just perform your own logic with the notification data payload.
I've been following the tutorial found at: https://azure.microsoft.com/en-us/documentation/articles/partner-xamarin-mobile-services-xamarin-forms-get-started-push/ to try and get push notifications to work in my Xamarin.Forms app.
I've got them working on Android, but I'm having a bug on iOS - I need to customize the text (from the phone) before the notification is actually made, but I can't on ios since when the app is running in the background, ReceivedRemoteNotification isn't being called.
Here's something similar to what my notification handling code looks like:
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
NSObject inAppMessage;
bool success = userInfo.TryGetValue(new NSString("inAppMessage"), out inAppMessage);
if (success)
{
//change the text that is displayed
string newNotText = ModifyNotification(inAppMessage.ToString());
var alert = new UIAlertView("Got push notification", newNotText, null, "OK", null);
alert.Show();
}
}
How can I customize a notification that is received on iOS?
iOS Push and GCM is different in how they work, GCM lets the App handle the notification and start the local notification, iOS does not.
iOS only notifies your App that the notification existed, but there are a workarounds for this.
On iOS you can use silent notifications which are not seen by the user but you'll get the ReceivedRemoteNotification callback
You can read more here: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html
This documentation tells you the following:
The content-available property with a value of 1 lets the remote notification act as a “silent” notification. When a silent notification arrives, iOS wakes up your app in the background so that you can get new data from your server or do background information processing. Users aren’t told about the new or changed information that results from a silent notification, but they can find out about it the next time they open your app.
So if your notification contains the "content-available" with value 1 it will be silent and you can start your own local notification after this.
Be prepared that this is not reliable in any way and if you are not a special privileged app(like VOIP) you are not able to do what you want in a reliable way on iOS
Backend example:
Just change the template var like in your tutorial used:
const string template = "{\"aps\":{\"content-available\":\"1\",\"alert\":\"$(message)\"}}";
Because it is not clear enough, if you don't want to get any notification you should not use alert or sound properties for your notification
const string template = "{\"aps\":{\"content-available\":\"1\",\"someproperty\":\"propertyvalue\"}}";
I've set up my app for push notifications, and for the past few days of development I've received zero notifications when the app is in the background. No alert, badges, sounds -- nada. Nothing shows up in the notifications area when you swipe down the screen from above.
But when the app is in the foreground, application:didReceiveRemoteNotification: does indeed fire off. When I first started messing around with notifications, I was getting them, but at some point it just stopped working. I've verified that the phone has notifications enabled for the app.
I'm using Quickblox to send cross-platform push notifications, and they have a control panel on their website where you can send notifications. When I sent one through there, I receive it in the background. On the foreground, this is what I see as the log output for the ones sent from the control panel:
2015-07-11 00:11:26.755 Viewerapp[6671:2177549] didReceiveRemoteNotification userInfo={
aps = {
alert = "Testing push notification";
sound = default;
};
}
And this is what I receive when the client app uses the Quickblox API to send a push notification:
2015-07-11 00:14:14.907 Viewerapp[6671:2177549] didReceiveRemoteNotification userInfo={
QBUserID = 2574021;
aps = {
alert = "";
};
messageOS = Android;
messageText = "Push notification test";
messageType = "simpleMessage";
userName = John;
}
Is the problem that the latter lacks data in aps? Does it seem like it's a Quickblox issue?