Xamarin iOS save on realm db when app is closed - ios

I would like to save a notification on realm db when push notification is received while app is closed, it works when is running in foreground or background, but when it is closed not works and I cant catch any exception.
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
if (null != userInfo && userInfo.ContainsKey(new NSString("aps")))
{
NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;
string title = "Agendarum Informa";
string notificationMessage = string.Empty;
if (aps.ContainsKey(new NSString("title")))
title = (aps[new NSString("title")] as NSString).ToString();
if (aps.ContainsKey(new NSString("alert")))
notificationMessage = (aps[new NSString("alert")] as NSString).ToString();
UIAlertView alert = new UIAlertView()
{
Title = title,
Message = notificationMessage
};
try
{
var now = DateTime.Now;
Realm _realm;
_realm = Realm.GetInstance();
_realm.Write(() =>
{
_realm.Add(new Models.RealmObjects.Notification()
{
Title = alert.Title,
Message = notificationMessage,
Date = now
});
});
}
catch (Exception ex)
{
UIAlertView alertEx = new UIAlertView()
{
Title = "ERRO",
Message = ex.Message
};
alertEx.AddButton("OK");
alertEx.Show();
}
alert.AddButton("OK");
alert.Show();
}
}
NOTE: On Android it works fine...
Any ideias?
Thanks.

Related

Unable to recieve notification in IOS xamarin form

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

Youtube Livestream Api LiveChatMessages List

Im trying to get the Messages from a Youtube Livestream, works, but i dont get new Messages. The NextPageToken is included.
Sometimes i get new messages, but it takes arround 5-10min.
Youtube Chat Sending works also fine.
Any Idea?
This is from the Docs: https://developers.google.com/youtube/v3/live/docs/liveChatMessages/list
private async Task GetMessagesAsync(string liveChatId, string nextPageToken, long? pollingIntervalMillis)
{
liveChatId = "EiEKGFVDVUQ3WGNXTk92SlpvaHFMM3dZTi1uZxIFL2xpdmU";
if (!updatingChat)
{
if (!string.IsNullOrEmpty(liveChatId))
{
newMessages = true;
var chatMessages = youTubeService.LiveChatMessages.List(liveChatId, "id,snippet,authorDetails");
var chatResponse = await chatMessages.ExecuteAsync();
PageInfo pageInfo = chatResponse.PageInfo;
newMessages = false;
if (pageInfo.TotalResults.HasValue)
{
if (!prevCount.Equals(pageInfo.TotalResults.Value))
{
prevCount = pageInfo.TotalResults.Value;
newMessages = true;
}
}
if (newMessages)
{
Messages = new List<YouTubeMessage>();
foreach (var chatMessage in chatResponse.Items)
{
string messageId = chatMessage.Id;
string displayName = chatMessage.AuthorDetails.DisplayName;
string displayMessage = chatMessage.Snippet.DisplayMessage;
string NextPagetoken = chatResponse.NextPageToken;
YouTubeMessage message = new YouTubeMessage(messageId, displayName, displayMessage);
if (!Messages.Contains(message))
{
Messages.Add(message);
string output = "[" + displayName + "]: " + displayMessage;
Console.WriteLine(time + output);
}
}
}
await GetMessagesAsync(liveChatId, chatResponse.NextPageToken, chatResponse.PollingIntervalMillis);
}
}
updatingChat = false;
await Task.Delay(100);
}
public async Task YouTubeChatSend(string message)
{
try
{
LiveChatMessage liveMessage = new LiveChatMessage();
liveMessage.Snippet = new LiveChatMessageSnippet()
{
LiveChatId = "EiEKGFVDVUQ3WGNXTk92SlpvaHFMM3dZTi1uZxIFL2xpdmU",
Type = "textMessageEvent",
TextMessageDetails = new LiveChatTextMessageDetails() { MessageText = message }
};
var insert = this.youTubeService.LiveChatMessages.Insert(liveMessage, "snippet");
var response = await insert.ExecuteAsync();
if (response != null)
{
}
}
catch
{
Console.WriteLine("Failed to chat send");
}
}

How to access parameters in Push Notification

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.

FCM custom notification for ios

I know this question have been ask a lot of time in android but not ios. So I already test out push notification with FCM it work fine. Mine problem is wether it's a way to create custom notification rather than letting the system to handle the notification with the notification payload?
-Users can send data messages with FCM.What you have to send is,
Sample PostMan Json data:
{ "data": {
"any key": "any value",
"any key 2": "any value 2"
},
"to" : "token received to mobile from FCM"
}
Payload inside "data" can change according to the requirement.
Mobile end:
application(_:didReceiveRemoteNotification:) override method will get fire.So it is unto developer to extract data from the userInfo property in iOS and use it.
For ios using c# working code:-
public bool NotificationToiosDevice()
{
bool str;
try
{
//Create the web request with fire base API
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
//serverKey - Key from Firebase cloud messaging server
tRequest.Headers.Add(string.Format("Authorization: key={0}", "AAAALNl-P7o:APA91bE38khU73UTdIj7L6LvVS3uI6f47REmxl.................................."));
//Sender Id - From firebase project setting
tRequest.Headers.Add(string.Format("Sender: id={0}", "12345"));
tRequest.ContentType = "application/json";
var payload = new
{
to = "dDDbFltwE5o:APA91bFmZZ-c1pNp................",
priority = "high",
content_available = true,
notification = new
{
title = "Title Of Notification",
},
data = new
{
body = new { Parameter1 = "FirstParameterValue", Parameter2 = "SecondParameterValue" },
},
};
string jsonNotificationFormat = Newtonsoft.Json.JsonConvert.SerializeObject(payload);
Byte[] byteArray = Encoding.UTF8.GetBytes(jsonNotificationFormat);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
if (dataStreamResponse != null) using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
// str = sResponseFromServer;
}
}
}
}
str = true;
}
catch (Exception ex)
{
str = false;
}
return str;
}

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