Reputation: 16199
First off I am using Xamarin Forms for a WP8, iOS and Android app.
Goal:
I want to go to a specific page when the toast is clicked depending upon the payload information of the toast notification.
I have push notifications using Azure Notification Hubs all setup and working well. I use MVVMLight and their dependency injection to setup push notifications specifically for each platform.
Each payload needs to be sent a little different due to the different formats required. With each you will notice I want to send a SignalId in the payload to perform a different action as required on the receiving device from regular push notifications.
Android
{
"data" : {
"msg" : "message in here",
"signalId" : "id-in-here",
},
}
iOS
{
"aps" : { "alert" : "message in here" },
"signalId" : "id-in-here"
}
Windows Phone 8
<?xml version="1.0" encoding="utf-8"?>
<wp:Notification xmlns:wp="WPNotification">
<wp:Toast>
<wp:Text1>category</wp:Text1>
<wp:Text2>message in here</wp:Text2>
<wp:Param>?signalId=id-in-here</wp:Param>
</wp:Toast>
</wp:Notification>
.
Question:
How do I get this information in a Xamarin Forms app and redirect to the appropriate page when the application is reactivated because the user clicked on the toast notification?
I want to get the payload information when the app loads, then say, yes this contains a SignalId, lets redirect to this page.
At the moment all it does it show the application when a toast notification is clicked. Must I do it specific to the app, or is there a Xamarin Forms way?
Any help appreciated even if you only know how to do it for one platform, I can probably work my way around the other platforms from there.
Upvotes: 3
Views: 2919
Reputation: 16199
I have found the way to do it for all platforms. Windows has been tested, Android and iOS haven't.
Windows and iOS work on a show toast notification if the app is in the background, or let your code deal with it if the app is in the foreground. Android shows the toast regardless of application status.
With Windows Phone 8 I need to go to the MainPage.xaml.cs and add in this override.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (this.NavigationContext.QueryString.ContainsKey("signalId"))
{
var signalId = this.NavigationContext.QueryString["signalId"];
var id = Guid.Empty;
if (signalId != null
&& Guid.TryParse(signalId, out id)
&& id != Guid.Empty)
{
this.NavigationContext.QueryString.Clear();
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// Do my navigation to a new page
});
}
}
}
For Android in the GcmService
protected override void OnMessage(Context context, Intent intent)
{
Log.Info(Tag, "GCM Message Received!");
var message = intent.Extras.Get("msg").ToString();
var signalId = Guid.Empty;
if (intent.Extras.ContainsKey("signalId"))
{
signalId = new Guid(intent.Extras.Get("signalId").ToString());
}
// Show notification as usual
CreateNotification("", message, signalId);
}
Then in the CreateNotification function put some extra information in the Intent.
var uiIntent = new Intent(this, typeof(MainActivity));
if (signalId != Guid.Empty)
{
uiIntent.PutExtra("SignalId", signalId.ToString());
}
Then in the MainActivity.cs override this function
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (data.HasExtra("SignalId"))
{
Guid signalId = new Guid(data.GetStringExtra("SignalId"));
if (signalId != Guid.Empty)
{
data.RemoveExtra("SignalId");
// Do you navigation
}
}
}
In iOS you will notice I have enhanced the default 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
var aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
var alert = string.Empty;
//Extract the alert text
// NOTE: If you're using the simple alert by just specifying
// " aps:{alert:"alert msg here"} " this will work fine.
// But if you're using a complex alert with Localization keys, etc.,
// your "alert" object from the aps dictionary will be another NSDictionary.
// Basically the json gets dumped right into a NSDictionary,
// so keep that in mind.
if (aps.ContainsKey(new NSString("alert")))
alert = ((NSString) aps[new NSString("alert")]).ToString();
// If this came from the ReceivedRemoteNotification while the app was running,
// we of course need to manually process things like the sound, badge, and alert.
if (!fromFinishedLaunching)
{
//Manually show an alert
if (!string.IsNullOrEmpty(alert))
{
var signalId = new Guid(options.ObjectForKey(new NSString("signalId")) as NSString);
// Show my own toast with the signalId
}
}
}
}
Then in the FinishedLaunching function check if there is any payload
// Check if any payload from the push notification
if (options.ContainsKey("signalId"))
{
var signalId = new Guid(options.ObjectForKey(new NSString("signalId")) as NSString);
// Do the navigation here
}
Upvotes: 3