I am trying to add push notifications to my Xamarin.iOS app using this tutorial
https://learn.microsoft.com/en-us/azure/notification-hubs/xamarin-notification-hubs-ios-push-notification-apns-get-started
I have followed all the steps as it is and below is what I have tried so far :-
AppDelegate.cs
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
// create a new window instance based on the screen size
Window = new UIWindow(UIScreen.MainScreen.Bounds);
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);
}
// If you have defined a root view controller, set it here:
UIStoryboard storyboard = UIStoryboard.FromName("Main", null);
var myViewController = storyboard.InstantiateViewController("Login_VC") as LoginViewController;
Window.RootViewController = myViewController;
// make the window visible
Window.MakeKeyAndVisible();
return true;
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
Hub = new SBNotificationHub(ServiceConstants.ListenConnectionString, ServiceConstants.NotificationHubName);
string token = deviceToken.ToString().Replace("<", "").Replace(">", "").Replace(" ", "");
deviceToken = NSData.FromString(token);
Hub.UnregisterAllAsync(deviceToken, (error) =>
{
if (error != null)
{
Console.WriteLine("Error calling Unregister: {0}", error.ToString());
return;
}
NSSet tags = null; // create tags if you want
Hub.RegisterNativeAsync(deviceToken, tags, (errorCallback) =>
{
if (errorCallback != null)
Console.WriteLine("RegisterNativeAsync error: " + errorCallback.ToString());
});
});
}
I have signed my app with a development provisioning profile from the apple developer console which is signed with an AppId with Push notifications enabled on it.
But when I get an error at the very beginning while registering for push notifications as follows :-
Error Response:<Error><Code>401</Code><Detail>ExpiredToken: .TrackingId:94e8c47b-1221-4188-8a75-9b744e12c9d7_G4,TimeStamp:1/20/2017 10:05:51 AM</Detail></Error>
Fail to perform registration operation.
<NSMutableURLRequest: 0x170018a70> { URL: https://mynotificationnamespace.servicebus.windows.net/mynotificationhub/Registrations/?$filter=deviceToken+eq+'62383062663335386437646233313263613766656165323535626634646537393438623262616238393164393466393766353030666166313966623339323232'&api-version=2013-04 }
Headers:{
Authorization = "SharedAccessSignature sr=http%3a%2f%2fmynotificationnamespace.servicebus.windows.net%2fmynotificationhub%2fregistrations%2f%3f%24filter%3ddevicetoken%2beq%2b%2762383062663335386437646233313263613766656165323535626634646537393438623262616238393164393466393766353030666166313966623339323232%27%26api-version%3d2013-04&sig=dpGnfYj19D%2FseR3GlTrE6Ay0ASdc%2BwFwWRNf3sxBE0%3D&se=148394919&skn=DefaultListenSharedAccessSignature";
"Content-Type" = "application/xml";
"User-Agent" = "NOTIFICATIONHUBS/2013-04(api-origin=IosSdk; os=iOS; os_version=10.2;)";
}
I am able to get the Push notifications working from the same Notification hub for Xamarin.Android but not Xamarin.iOS.
Any help would be appreciated.
Answering my own question as it might be useful for people looking for something similar. Turns out the Automatic DateTime was disabled on my device hence the device token was fetching as invalid or expired as the time on the device was lagging behind with 30 mins.
Related
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.
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));
});
}
I have been struggling with this for several days and have found many other posts on the subject, but nothing seems to fix the problem I have. I have a feeling this might be simple as I have tried this several times with cut down projects and always get the same failure. I can receive Firebase messages fine in Android, but iOS consistently defeats me.
I am using a phone with iOS 10 as a test. The debug code always gets a token back, but on connecting, an error 'The operation couldn’t be completed. (com.google.fcm error 501.)' is returned. I attach some sample code - this has been bodged around in frustration
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)
{
global::Xamarin.Forms.Forms.Init ();
LoadApplication (new FirebaseTest.App (""));
RegisterForNotificationFCM();
return base.FinishedLaunching (app, options);
}
void RegisterForNotificationFCM()
{
// 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.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.Analytics.Loader loader1 = new Firebase.Analytics.Loader();
Firebase.InstanceID.Loader loader2 = new Firebase.InstanceID.Loader();
//Firebase.Core.App.Configure();
Firebase.InstanceID.InstanceId.Notifications.ObserveTokenRefresh((sender, e) =>
{
var newToken = Firebase.InstanceID.InstanceId.SharedInstance.Token;
System.Diagnostics.Debug.WriteLine(newToken);
connectFCM();
});
}
public override void DidEnterBackground(UIApplication uiApplication)
{
Messaging.SharedInstance.ShouldEstablishDirectChannel = false;
}
public override void OnActivated(UIApplication uiApplication)
{
base.OnActivated(uiApplication);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
Messaging.SharedInstance.ApnsToken = deviceToken;
connectFCM();
//Firebase.InstanceID.InstanceId.SharedInstance.SetApnsToken(deviceToken, Firebase.InstanceID.ApnsTokenType.Prod);
}
public void DidRefreshRegistrationToken(Messaging msg, string str)
{
}
//Fire when background received notification is clicked
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
//Messaging.SharedInstance.AppDidReceiveMessage(userInfo);
System.Diagnostics.Debug.WriteLine(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);
}
}
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
// Do your magic to handle the notification data
System.Console.WriteLine(notification.Request.Content.UserInfo);
}
// Receive data message on iOS 10 devices.
public void ApplicationReceivedRemoteMessage(RemoteMessage remoteMessage)
{
Console.WriteLine(remoteMessage.AppData);
}
private void connectFCM()
{
//Messaging.SharedInstance.ShouldEstablishDirectChannel = true;
//Messaging.SharedInstance.Subscribe("/topics/topic");
Messaging.SharedInstance.Connect((error) =>
{
if (error == null)
{
Messaging.SharedInstance.Subscribe("/topics/topic");
}
System.Diagnostics.Debug.WriteLine(error != null ? "error occured" : "connect success");
});
}
These functions have been removed from many other posts on the same subject as happens when you get more and more desperate. I think the firebase console has been set up okay. I have added the iOS as an app along side the working Android one and have added an authentication key created on the Mac. (surprisingly I still get a token back even without this iOS app as part of the firebase project - not what I expected) A certificate has been created for this app and the provisioning profile has been recreated and old ones deleted.
I'm not sure what else to add - someone please put me out of my misery...
Got there in the end. Things for other people to check on - Moved App.Configure() into connectFCM
private void connectFCM()
{
Firebase.Core.App.Configure();
Messaging.SharedInstance.ShouldEstablishDirectChannel = true;
}
and added the following to info.plist
<key>NSExceptionDomains</key>
<dict>
<key>firebaseio.com</key>
<dict>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
I am using mvvmCross 5.3 and Xamarin 6.3 and need help to access data passed by notification.
When I get a notification, I'm getting a standard JSON that is sent by Apple. I also receive one more parameter that I'll use to point to some screen in my application.
In my AppDelegate, I have the following code:
public override bool FinishedLaunching(UIApplication application, NSDictionary options)
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var setup = new Setup(this, Window);
setup.Initialize();
var startup = Mvx.Resolve<IMvxAppStart>();
startup.Start();
Window.MakeKeyAndVisible();
//Push Notifications
if (UIDevice.CurrentDevice.CheckSystemVersion(9, 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);
}
return ApplicationDelegate.SharedInstance.FinishedLaunching(application, options);
}
In the parameter options, I know that I get the information I need. I do not know how to access this information in my code.
2017-10-26 11:39:28.680 App.IOs[6733:2676232]
{
UIApplicationLaunchOptionsRemoteNotificationKey =
{
aps =
{
alert =
{
body = "Message";
title = "Title";
};
};
idOrder = 254;
};
}
You can create a method like this and call it in the iOS methods that receive the notifications in AppDelegate:
private void HandleReceivedNotification(NSDictionary userInfo = null)
{
if (userInfo != null)
{
var apsDictionary = userInfo["aps"] as NSDictionary;
var alertDictionary = apsDictionary["alert"] as NSDictionary;
var body = alertDictionary["body"].ToString();
var idOrder = userInfo["idOrder "].ToString();
}
}
But don't forget to include a try/catch and check if any variable is null.
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.