Unable to recieve notification in IOS xamarin form - ios

I have developed app for ios and android in xamarin form cross platform. The problem I am facing in notification is that i can receive notification in android and its working absolutely fine, even I can open specific page from notification data, but in IOS I am not able to receieve notification. Here is my code from where I am sending notification
public async void NewTaskNotification(string user_token, string titlee, string bodyy, string openpage, long? mrno, DateTime? appointmentdate)
{
i++;
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
tRequest.ContentType = "application/json";
var objNotification = new
{
to = user_token,
data = new
{
title = titlee,
body = bodyy,
priority = "high",
id = i,
icon = "ic_stat_ic_stat_ic_notification",
color = "#2F3C51",
Background = "#2F3C51",
open_page = openpage,
mr_no = mrno,
appointmentDate = appointmentdate,
},
};
string jsonNotificationFormat = Newtonsoft.Json.JsonConvert.SerializeObject(objNotification);
Byte[] byteArray = Encoding.UTF8.GetBytes(jsonNotificationFormat);
tRequest.Headers.Add(string.Format("Authorization: key={0}", "AAAAoQ445fk:APA91bHagr12v6bGUqE2d8soHCMXwo4rD6wyM_LFp6yD9b968J3SQQ9u8T5rsFBtsPzL-ct_cCjad_YPpEjaw5tq_OqR_asB5-zgKqyQfhV2djFxAAbK7PBPCZHMI2Y6KmNN8R-MItOA"));
tRequest.Headers.Add(string.Format("Sender: id={0}", "691728344569"));
tRequest.ContentLength = byteArray.Length;
tRequest.ContentType = "application/json";
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String responseFromFirebaseServer = tReader.ReadToEnd();
FCMResponse response = Newtonsoft.Json.JsonConvert.DeserializeObject<FCMResponse>(responseFromFirebaseServer);
if (response.success == 1)
{
Console.WriteLine("succeeded");
}
else if (response.failure == 1)
{
Console.WriteLine("failed");
}
}
}
}
}
}
with this code i am able to recieve notification and even open specific page but only with android, its not working with ios, but when i try to send notification to IOS from firebase console, its working fine.
Here is my appdelegate.cs
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions)
{
Rg.Plugins.Popup.Popup.Init();
CachedImageRenderer.Init();
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
FirebasePushNotificationManager.Initialize(launchOptions, true);
FirebasePushNotificationManager.CurrentNotificationPresentationOption = UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Badge;
UNUserNotificationCenter.Current.Delegate = new UserNotificationCenterDelegate();
return base.FinishedLaunching(uiApplication, launchOptions);
}
public class UserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
public UserNotificationCenterDelegate()
{
}
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
// Do something with the notification
Console.WriteLine("Active Notification: {0}", notification);
// Tell system to display the notification anyway or use
// `None` to say we have handled the display locally.
completionHandler(UNNotificationPresentationOptions.Alert);
}
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
FirebasePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
}
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
FirebasePushNotificationManager.RemoteNotificationRegistrationFailed(error);
}
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
FirebasePushNotificationManager.DidReceiveMessage(userInfo);
// Do your magic to handle the notification data
System.Console.WriteLine(userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
}
}
I need to know where I am doing wrong for IOS

Related

iOS Background notification C# Xamarin via Firebase

I am sending Firebase Notification on devices with Xamarin plugin.
This is my configuration : Visual Studio 2022. iOS 15. Xcode 13.
All is working fine in Android devices.
All is working fine in Apple devices except one thing : When the application is in background, the notification is received only when the user open the application.
Here is my code :
public class MVision : UIApplicationDelegate, IUNUserNotificationCenterDelegate, IMessagingDelegate
{
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions){
Firebase.Core.App.Configure();
// Messaging.SharedInstance.Self
// Messaging.messaging().delegate = self
Messaging.SharedInstance.Delegate = (IMessagingDelegate)Self;
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// Request Permissions
UNUserNotificationCenter.Current.RequestAuthorization(
UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound,
(granted, error) =>
{
// Do something if needed
});
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = new MyUNUserNotificationCenterDelegate();
// For iOS 10 data message (sent via FCM)
Messaging.SharedInstance.Delegate = this;
}
else
{
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert
| UIUserNotificationType.Badge
| UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings
.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
Messaging.SharedInstance.ShouldEstablishDirectChannel = true;
UNUserNotificationCenter.Current.Delegate = new MyUNUserNotificationCenterDelegate();
UIApplication.SharedApplication.RegisterForRemoteNotifications();
The methods are :
[Export("messaging:didReceiveRegistrationToken:")]
public void DidReceiveRegistrationToken(Messaging messaging, string fcmToken)
{
var i = 1;
// var token = Messaging.SharedInstance.FcmToken;
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
[Export("messaging:didRegisterForRemoteNotificationsWithDeviceToken:")]
public void DidRegisterForRemoteNotificationsWithDeviceToken(UIKit.UIApplication application, Foundation.NSData deviceToken) {
Messaging.SharedInstance.ApnsToken = deviceToken;
}
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) { var userInfo1 = userInfo; }
[Export("application:didReceiveNotificationResponse:fetchCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, System.Action completionHandler)
{
completionHandler();
}
[Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
public override void DidReceiveRemoteNotification(
UIApplication application,
NSDictionary userInfo,
System.Action<UIBackgroundFetchResult> completionHandler)
{
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// Except if "content-available" is set to true / 1
// Print full message.
// Console.WriteLine(userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
}
[Export("messaging:didReceiveMessage:")]
public void DidReceiveMessage(Messaging messaging, RemoteMessage remoteMessage)
{
var notification = (NSDictionary)remoteMessage.AppData.ValueForKey(new NSString("notification"));
var title = notification.ValueForKey(new NSString("title"));
var text = notification.ValueForKey(new NSString("body"));
// remotenotification = true;
ScheduleNotification(title.ToString(), text.ToString());
}
//This code is for showing notification
void ScheduleNotification(string title, string body)
{
// Create content
var content = new UNMutableNotificationContent();
content.Title = title;
//content.Subtitle = "Subtitle";
content.Body = body;
content.Badge = 1;
content.CategoryIdentifier = "notification_fv";
content.Sound = UNNotificationSound.Default;
// Fire trigger in one seconds
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(1, false);
var requestID = "customNotification";
var request = UNNotificationRequest.FromIdentifier(requestID, content, trigger);
// This is the line that does the trick
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) => {
if (err != null)
{
// Report error
System.Console.WriteLine("Error: {0}", err);
}
else
{
// Report Success
System.Console.WriteLine("Notification Scheduled: {0}", request);
}
});
}
/* [Export("messaging:didReceiveMessage:")]
public void DidReceiveMessage(Messaging messaging, RemoteMessage remoteMessage)
{
// Handle Data messages for iOS 10 and above.
HandleMessage(remoteMessage.AppData);
var fcmToken = Messaging.SharedInstance.FcmToken;
}*/
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, System.Action<UNNotificationPresentationOptions> completionHandler)
{
SystemSound.Vibrate.PlayAlertSound();
SystemSound.Vibrate.PlaySystemSound();
completionHandler(UNNotificationPresentationOptions.Alert);
}
The notification center delegate class is :
using Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;
using UserNotifications;
namespace MVision.iOS
{
public class MyUNUserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
bool toggle;
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
if (toggle)
completionHandler(UNNotificationPresentationOptions.Alert);
else
{
// Console.WriteLine(notification);
// completionHandler(UNNotificationPresentationOptions.None);
completionHandler(UNNotificationPresentationOptions.Alert);
}
toggle = !toggle;
}
}
}
I check the info.plist
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<key>FirebaseScreenReportingEnabled</key>
<true/>
I also refer to entitlement.developer.plist :
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
I also parameter my notification with content-available = 1 and mutable-content = 1.
I think that the problem is that "DidReceiveRemoteNotification" is never call neither in background, nor in foreground.
Any Ideas ?
Please also notice : In Xamarin, when you stay in Visual Studio 2019 and you pass to iOS 15, you will not have simulators anymore, please download Visual Studio 2022.
Entitlement.plist does not work on this configuration. You must create Entitlement.developer.plist and refer to is.

xamarin push notification ios Page navigation not working when push notification click

I have azure push notification in Xamarin forms. when push notification received I need to open a page in my application. Its working fine in android. In iOS its not working when app is open. When app is in the background its working find in iOS.
This is my App Delegate code
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
Action<UIBackgroundFetchResult> completionHandler)
{
try
{
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
NSError error;
NSData notification = NSJsonSerialization.Serialize(userInfo["action"], NSJsonWritingOptions.PrettyPrinted, out error);
string notificationString = NSString.FromData(notification, NSStringEncoding.UTF8).ToString();
var NotificationObj = JsonConvert.DeserializeObject<NotificationData>(notificationString);
NotificationService.pushPageName = NotificationObj.Notification[0].PageName.ToString();
NotificationService.pushAppName = NotificationObj.AppName.ToString();
NotificationService.OpenPages = NotificationObj.Notification[0].OpenPage;
NotificationService.Notification = notificationString;
if (UIApplication.SharedApplication.ApplicationState.Equals(UIApplicationState.Active))
{
//App is in foreground. Act on it.
var application1 = new App(NotificationService.pushPageName, NotificationService.pushAppName, NotificationService.Notification);
LoadApplication(application1);
}
else
{
// var application1 = new App(NotificationService.pushPageName, NotificationService.pushAppName, NotificationService.Notification);
// LoadApplication(application1);
}
}
catch (Exception ex)
{
//LogInfo.ReportErrorInfo(ex.Message, ex.StackTrace, "AppDelegate-DidReceiveRemoteNotification");
}
}
after click push notification I need to open splash screen again.
This is App.cs Code
public App(string openPageName, string openAppName,string notification)
{
ServiceContainer.Resolve<IPushNotificationActionService>()
.ActionTriggered += NotificationActionTriggered;
InitMainPage(openPageName, openAppName, notification);
}
private void InitMainPage(string pageName,string appName,string notification)
{
ServiceContainer.Resolve<IPushNotificationActionService>()
.ActionTriggered += NotificationActionTriggered;
PushNotificationActionService.PushNotificationPageName = pageName ;
PushNotificationActionService.PushNotificationAppName = appName;
PushNotificationActionService.PushNotificationMessage = notification;
MainPage = new NavigationPage(new Splash(pageName));
}
All methods are calling and push notification data also loading correctly in iOS. But not navigating to Spalsh Screen. Anyone have an idea to resolve this please help.
If the app is running, we don't need to reload app with LoadApplication , we can directly send message to set MainPage in App.cs .
iOS
if (UIApplication.SharedApplication.ApplicationState.Equals(UIApplicationState.Active))
{
MessagingCenter.Send<object>(this,"Hi");
}
Forms
public App()
{
InitializeComponent();
MainPage = new MainPage();
MessagingCenter.Subscribe<object>(this, "Hi", (obj) => {
MainPage = new NavigationPage(new Splash(pageName));
});
}

Xamarin Firebase iOS not receiving FCM messages

I tried to implement Firebase push notifications and messages in my Xamarin Forms application. In Android it works fine, while in iOS I am receiving push notifications but I'm not receiving FCM data-only messages.
I am using Xamarin.Firebase.iOS.CloudMessaging package, and I followed this guide and this other one too.
This is my AppDelegate.cs code:
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate, IMessagingDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Forms.SetFlags("Brush_Experimental");
Rg.Plugins.Popup.Popup.Init();
//Ascetic.Plugins.PopupDecorations.iOS.PrettyPopup.Init();
global::Xamarin.Forms.Forms.Init();
SfListViewRenderer.Init();
new Syncfusion.SfAutoComplete.XForms.iOS.SfAutoCompleteRenderer();
Syncfusion.XForms.iOS.TabView.SfTabViewRenderer.Init();
iOSMaterialFrameRenderer.Init();
LoadApplication(new App());
// Register your app for remote notifications.
configureFirebase();
var result = base.FinishedLaunching(app, options);
app.KeyWindow.TintColor = UIColor.White;
foreach (var fs in UIFont.FamilyNames.OrderBy(c => c).ToList())
{
Console.WriteLine(" * " + fs);
foreach (var f in UIFont.FontNamesForFamilyName(fs).OrderBy(c => c).ToList())
{
Console.WriteLine(" *-- " + f);
}
}
return result;
}
private void configureFirebase()
{
Firebase.Core.App.Configure();
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = this;
// iOS 10 or later
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
{
});
// For iOS 10 data message (sent via FCM)
Messaging.SharedInstance.Delegate = this;
}
else
{
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
//Firebase
[Export("messaging:didReceiveRegistrationToken:")]
public void DidReceiveRegistrationToken(Messaging messaging, string fcmToken)
{
Preferences.Set("tokenNotifica", fcmToken);
Console.WriteLine("\nValue: " + (fcmToken));
}
//APP IN BACKGROUND
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
handleNotification(userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
}
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification,
Action<UNNotificationPresentationOptions> completionHandler)
{
handleNotification(notification.Request.Content.UserInfo);
completionHandler(UNNotificationPresentationOptions.Sound | UNNotificationPresentationOptions.Alert);
}
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action
completionHandler)
{
completionHandler();
NSDictionary userInfo = response.Notification.Request.Content.UserInfo;
try
{
var Data = userInfo[new NSString("gcm.notification.data")] as NSString;
if (Data != null && Data != "")
{
string[] tokens = Data.ToString().Split(',');
string Username = tokens[0];
string Password = tokens[1];
var Title = string.IsNullOrEmpty(response.Notification.Request.Content.Title) ? "No Notification available" : response.Notification.Request.Content.Title;
var Body = string.IsNullOrEmpty(response.Notification.Request.Content.Body) ? "No Message available" : response.Notification.Request.Content.Body;
}
}
catch (Exception)
{
}
}
[Export("messaging:didReceiveMessage:")]
public void DidReceiveMessage(Messaging messaging, RemoteMessage message)
{
handleNotification(message.AppData);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
Messaging.SharedInstance.ApnsToken = deviceToken;
}
public void ApplicationReceivedRemoteMessage(RemoteMessage remoteMessage)
{
;
}
}
The DidReceiveRegistrationToken method is called with the token. If I send a notification to that token the method DidReceiveRemoteNotification is called, and the notification is successfully shown by the device. But if I send a data-only message to that token, nothing is called.
I tried disabling swizzling, enabling it, reconfigure Firebase from scratch and delete and recreate certificates and provisioning profiles in the Apple Dev website, but nothing worked. Also, I think all is configured correctly since my app is receiving notifications.
I hope I gave enough information, I am struggling with this for weeks
EDIT
I use this function in php to send the data-only message to devices
function sendMessage($deviceKey, $data){
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
"Content-Type: application/json",
"project_id: ***",
"Authorization: key=***"
));
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, [
CURLOPT_URL => 'https://fcm.googleapis.com/fcm/send',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_USERAGENT => 'Codular Sample cURL Request',
CURLOPT_POST => 1,
]);
$body = [
'to' => $deviceKey,
"data" => $data
];
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body));
$res = json_decode(curl_exec($curl), true);
curl_close($curl);
return $res;
}
This function is equal to the function that send the notification, but the $body array doesn't contain a "notification" key.
What I would like to do is use the data payload of the message in the application without display the notification, and this works just fine in Android, but not in iOS.

FCM Xamarin.Forms, iOS background Notification doesnt show

Platform: iOS 10.2+
Xamarin Plugin: Firebase iOS cloud messaging https://components.xamarin.com/view/firebaseioscloudmessaging
Problem: When I send a notification from FireBase console or from my code calling FireBase. My iPhones don't receive the background notifications(as a bubble). But, if I had the application in foreground, I received the notification as a "DisplayAlert" from the function ApplicationReceivedRemoteMessage(RemoteMessage remoteMessage).
So, the device is registered on FCM, the device have the token, the device can receive the notifications, but the device didnt receive the notifications on background.
** In VisualStudio 2017 at .iOS project manifest I have the Background mode activated and the remote notifications activated too **
¿It's this a common issue? ¿Can I solve for working at my project?
Code of AppDelegate
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate, IMessagingDelegate
{
protected SQLiteAsyncConnection conn;
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
global::Xamarin.FormsMaps.Init();
CachedImageRenderer.Init();
LoadApplication(new App());
UITabBar.Appearance.SelectedImageTintColor = UIColor.FromRGB(139, 194, 77);
UINavigationBar.Appearance.TintColor = UIColor.FromRGB(139,194,77);
CrossVersionTracking.Current.Track();
// Firebase component initialize
Firebase.Analytics.App.Configure();
// Register your app for remote notifications.
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// iOS 10 or later
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => {
Console.WriteLine(granted);
});
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = this;
// For iOS 10 data message (sent via FCM)
Messaging.SharedInstance.RemoteMessageDelegate = this;
}
else
{
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
Firebase.InstanceID.InstanceId.Notifications.ObserveTokenRefresh((sender, e) =>
{
newToken = Firebase.InstanceID.InstanceId.SharedInstance.Token;
//Conectamos con la base de datos.
database = new SQLiteClient();
conn = database.GetConnection();
usuario = null;
try
{
var task = Task.Run(async () =>
{
usuario = await conn.Table<Usuario>()
.FirstOrDefaultAsync();
});
task.Wait();
if (usuario != null)
{
usuario.token = newToken;
task = Task.Run(async () =>
{
await conn.InsertOrReplaceAsync(usuario);
});
task.Wait();
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("TOKEN ERROR\tNo se ha podido Guardar el Token" + ex.Message);
}
System.Diagnostics.Debug.WriteLine("TOKEN\t" + newToken);
connectFCM();
});
#endregion
return base.FinishedLaunching(app, options);
}
public override void DidEnterBackground(UIApplication uiApplication)
{
Messaging.SharedInstance.Disconnect();
Console.WriteLine("Disconnected from FCM");
}
public override void OnActivated(UIApplication uiApplication)
{
connectFCM();
base.OnActivated(uiApplication);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
#if DEBUG
Firebase.InstanceID.InstanceId.SharedInstance.SetApnsToken(deviceToken, Firebase.InstanceID.ApnsTokenType.Sandbox);
#endif
#if RELEASE
Firebase.InstanceID.InstanceId.SharedInstance.SetApnsToken(deviceToken, Firebase.InstanceID.ApnsTokenType.Prod);
#endif
}
// iOS 9 <=, fire when recieve notification foreground
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
Messaging.SharedInstance.AppDidReceiveMessage(userInfo);
// Generate custom event
NSString[] keys = { new NSString("Event_type") };
NSObject[] values = { new NSString("Recieve_Notification") };
var parameters = NSDictionary<NSString, NSObject>.FromObjectsAndKeys(keys, values, keys.Length);
// Send custom event
Firebase.Analytics.Analytics.LogEvent("CustomEvent", parameters);
if (application.ApplicationState == UIApplicationState.Active)
{
System.Diagnostics.Debug.WriteLine(userInfo);
var aps_d = userInfo["aps"] as NSDictionary;
var alert_d = aps_d["alert"] as NSDictionary;
var body = alert_d["body"] as NSString;
var title = alert_d["title"] as NSString;
debugAlert(title, body);
}
}
// iOS 10, fire when recieve notification foreground
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
System.Console.WriteLine(notification.Request.Content.UserInfo);
var title = notification.Request.Content.Title;
var body = notification.Request.Content.Body;
debugAlert(title, body);
}
private void connectFCM()
{
Console.WriteLine("connectFCM\tEjecutandose la función.");
Messaging.SharedInstance.Connect((error) =>
{
if (error == null)
{
//TODO: Change Topic to what is required
Messaging.SharedInstance.Subscribe("/topics/all");
}
//System.Diagnostics.Debug.WriteLine("connectFCM\t" + (error != null ? "error occured" : "connect success"));
Console.WriteLine("connectFCM\t" + (error != null ? "error occured" + error.DebugDescription : "connect success"));
});
}
private void debugAlert(string title, string message)
{
var alert = new UIAlertView(title ?? "Title", message ?? "Message", null, "Cancel", "OK");
alert.Show();
}
public void ApplicationReceivedRemoteMessage(RemoteMessage remoteMessage)
{
Console.WriteLine("\n*******************************************");
Console.WriteLine("AplicationReceivedRemoteMessage\t" + remoteMessage.AppData);
Console.WriteLine("\n*******************************************");
var title = remoteMessage.AppData.ValueForKey(new NSString("title"));
var text = remoteMessage.AppData.ValueForKey(new NSString("text"));
debugAlert("" + title, "" + text);
}
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
debugAlert("DidreceiveNotificationResponse", response + "" );
}
For more info, my info.plist contais the key:
<key>UIBackgroundModes</key>
<array>
<string>location</string>
<string>bluetooth-central</string>
<string>bluetooth-peripheral</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
After a long investigation I solve it.
It is necesary to add that key to Entile.plist file.
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>

Push Notification in Xamarin Forms

I'm trying to implement Push Notification in PCL app in Xamarin forms IOS. I have a suitable provisioning profile and p12 file that I used to send notification to native app and I'm using it on my Xamarin forms, do I need to do something more beside this changes? I changed the AppDelegate in the IOS project to look like this:
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using UIKit;
namespace Punteam.iOS
{
[Register ("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
String model = UIDevice.CurrentDevice.Model;
String sysName = UIDevice.CurrentDevice.SystemName;
String sysVer = UIDevice.CurrentDevice.SystemVersion;
NSUserDefaults.StandardUserDefaults.SetString (model, "Model");
NSUserDefaults.StandardUserDefaults.SetString (sysName, "sysName");
NSUserDefaults.StandardUserDefaults.SetString (sysName, "sysVer");
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
{
var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
new NSSet());
UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
else
{
UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
//***********************************************************************************************
//** RegisteredForRemoteNotifications *
//***********************************************************************************************
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
// Get current device token
var DeviceToken = deviceToken.Description;
if (!string.IsNullOrWhiteSpace(DeviceToken)) {
DeviceToken = DeviceToken.Trim('<').Trim('>');
}
// Get previous device token
var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken");
// Has the token changed?
if (string.IsNullOrEmpty(oldDeviceToken) || !oldDeviceToken.Equals(DeviceToken))
{
//TODO: Put your own logic here to notify your server that the device token has changed/been created!
}
// Save new device token
NSUserDefaults.StandardUserDefaults.SetString(DeviceToken, "PushDeviceToken");
}
//***********************************************************************************************
//** ReceivedRemoteNotification *
//***********************************************************************************************
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
ProcessNotification(userInfo, false);
}
//***********************************************************************************************
//** ProcessNotification *
//***********************************************************************************************
void ProcessNotification(NSDictionary options, bool fromFinishedLaunching)
{
// Check to see if the dictionary has the aps key. This is the notification payload you would have sent
if (null != options && options.ContainsKey(new NSString("aps")))
{
//Get the aps dictionary
NSDictionary aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
string alertString = string.Empty;
string paramString = string.Empty;
if (aps.ContainsKey(new NSString("alert")))
alertString = (aps[new NSString("alert")] as NSString).ToString();
if (aps.ContainsKey(new NSString("param")))
paramString = (aps[new NSString("param")] as NSString).ToString();
if (!fromFinishedLaunching)
{
//Manually show an alert
if (!string.IsNullOrEmpty(alertString))
{
UIAlertView avAlert = new UIAlertView("Awesome Notification", alertString , null,
NSBundle.MainBundle.LocalizedString("Cancel", "Cancel"),
NSBundle.MainBundle.LocalizedString("OK", "OK"));
avAlert.Clicked += (sender, buttonArgs) =>
{
if (buttonArgs.ButtonIndex != avAlert.CancelButtonIndex)
{
if (!string.IsNullOrEmpty(paramString))
{
// App.Current.MainPage = new NavigationPage(new PushNotifMessageDisplay(paramString));
}
}
};
avAlert.Show();
}
}
}
}
//***********************************************************************************************
//** FailedToRegisterForRemoteNotifications *
//***********************************************************************************************
public override void FailedToRegisterForRemoteNotifications (UIApplication application , NSError error)
{
new UIAlertView("Error registering push notifications", error.LocalizedDescription, null, "OK", null).Show();
}
}
}
You can check my full example for push notification here
Regarding the iOS part, this is the relevant code that goes to your AppDelegate:
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
var deviceTokenString = deviceToken.ToString().Replace("<","").Replace(">", "").Replace(" ", "");
var notificationService = Resolver.Resolve<IPushNotificationService>();
var pushNotificationRegister = Resolver.Resolve<IPushNotificationRegister>();
if (pushNotificationRegister.ShouldSendToken(deviceTokenString))
{
var uid = UIDevice.CurrentDevice.IdentifierForVendor.AsString();
notificationService.AddPushToken(deviceTokenString, DeviceUtils.GetDeviceType(), uid);
}
}
*IPushNotificationRegister - checks if the token is already sent to the server (it is done to avoid unneeded requests to the server).
*IPushNotificationService - The service to send the token to the server.

Resources