Processing Notifications In Xamarin Forms Android
Solution 1:
Ok so it took me some time to figure this one out. OnNewIntent
is called when the app is in the background and the notification is clicked on. It is also called each time the app is minimized and the brought back up... so to tell the difference between the 2 events, you need to check the passed in Intent
for what extra data is inside it. The extra data would have come from the Intent
you made when you first initiated the notification.
Also make sure to set your MainActivity
's LaunchMode
to LaunchMode.SingleTop
so that your app does not get restarted each time the notification is clicked on.
[Activity(LaunchMode = LaunchMode.SingleTop, ....)]
publicclassMainActivity : FormsApplicationActivity {
....
///<summary>/// Called when the app is in the background and a notification is clicked on (also called each time the app is minimized and the brought back up), a new <c>Intent</c> is created/// and sent out, since we use <c>LaunchMode</c> set to <c>SingleTop</c> this method is called instead of the app being restarted.///</summary>///<param name="intent">The <c>Intent</c> that was set when the call was made. If started from a notification click, extra <c>string</c> values can be extracted.</param>protectedoverridevoidOnNewIntent(Intent intent) {
if(intent.HasExtra("Some special key you made up")) { //Here is where you check for special notification intent extras//Do something brilliant now that you know a notification was clicked on
}
base.OnNewIntent(intent);
}
To see how you can add data to the Intent
you can check out the Xamarin Sport App, but do not get too bogged down in all the other stuff they are doing like I always tend to do. Just focus on the PutExtra
part.
Edit #1:
If your app is completely closed, you need to pull the data from the Intent
passed into OnCreate
and pass it into your App
class or do something else with it:
protectedoverrideasyncvoidOnCreate(Android.OS.Bundle bundle) {
base.OnCreate(bundle);
Forms.Init(this, bundle);
string parameterValue = Intent.GetStringExtra("Some special key you made up"); //This would come in from the Push Notification being clicked on
Console.WriteLine("\nIn MainActivity.OnCreate() - Param Intent Extras: {0}\n", parameterValue);
//MessagingCenter.Send("nothing", ConstantKeys.NewNotification); //Do something special with the notification data
LoadApplication(parameterValue != null ? new App(parameterValue) : new App()); //Do something special with the notification data
}
Edit #2:
Some changes I would recommend to your OnReceive
method based on my current code (some may not be necessary, but it is just what I am doing):
- Label your Broadcast Receiver
- Add stupid Xamarin constructors
- Used constant property instead of string for IntentFilter
- Remove IntentFilter Priority
- Check for null Intent (might not be necessary)
- Use Application.Context instead of Forms.Context (I use Forms.Context in other parts of my app so not sure about this one, but can't hurt)
- Do not overwrite the passed in Intent
- Create startup intent instead of regular
- Add IncludeStoppedPackages flag before pulling out extras
- Check for boot completed event
- Use Notification.Builder instead of NotificationCompat.Builder (though you might need to change this back)
- Add following flags to pendingintent: PendingIntentFlags.UpdateCurrent | PendingIntentFlags.OneShot -- Use NotificationManager (unless you have a specific reason you commented it out)
[assembly: UsesPermission(Android.Manifest.Permission.Vibrate)]
[assembly: UsesPermission(Android.Manifest.Permission.WakeLock)] //Optional, keeps the processor from sleeping when a message is received
[assembly: UsesPermission(Android.Manifest.Permission.ReceiveBootCompleted)] //Allows our app to be opened and to process notifications even when the app is closednamespaceYour.App.Namespace {
[BroadcastReceiver(Enabled = true, Label = "GCM Alarm Notifications Broadcast Receiver")]
[IntentFilter(new []{ Intent.ActionBootCompleted })]
publicclassAlarmBroadcastReceiver : BroadcastReceiver {
#region Constructors// ReSharper disable UnusedMember.GlobalpublicAlarmBroadcastReceiver() { }
publicAlarmBroadcastReceiver(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { }
// ReSharper restore UnusedMember.Global#endregionpublicvoidRemind(DateTime dateTime, string msgtype, string usermedid) {
DateTime now = DateTime.Now;
var diffinseconds = (dateTime - now).TotalSeconds;
Intent alarmIntent = new Intent(Application.Context, typeof(AlarmBroadcastReceiver));
alarmIntent.PutExtra("notificationtype", msgtype);
alarmIntent.PutExtra("id", id);
PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
AlarmManager alarmManager = (AlarmManager)Application.Context.GetSystemService(Context.AlarmService);
//TODO: For demo set after 5 seconds.
alarmManager.Set(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime() + diffinseconds * 1000, pendingIntent);
}
publicoverridevoidOnReceive(Context context, Intent intent) {
#region Null Checkif(intent == null) {
Console.WriteLine("\nIn AlarmBroadcastReceiver.OnReceive() - Intent is null\n");
return;
}
#endregion
intent.AddFlags(ActivityFlags.IncludeStoppedPackages);
string action = intent.Action;
Console.WriteLine("\nIn AlarmBroadcastReceiver.OnReceive() - Action: {0}\n", action);
#region Boot Completed Checkif(action.Equals("android.intent.action.BOOT_COMPLETED")) {
PowerManager pm = PowerManager.FromContext(context);
PowerManager.WakeLock sWakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "GCM Broadcast Receiver Tag");
sWakeLock.Acquire();
Console.WriteLine("\nIn AlarmBroadcastReceiver.OnReceive() - Process Shared Preferences Notifications\n");
#region Process Saved Scheduled Notifications//Get list of saved scheduled notifications that did not fire off before the device was turned off (I store them in SharedPreferences and delete them after they are fired off)//Go through the list and reschedule them#endregion
sWakeLock.Release();
return;
}
#endregionstring notificationtype = intent.GetStringExtra("notificationtype");
Intent startupIntent = Application.Context.PackageManager.GetLaunchIntentForPackage(Application.Context.PackageName);
startupIntent.PutExtra("notificationtype", notificationtype);
// Instantiate the builder and set notification elements, including pending intent:
Notification.Builder builder = new Notification.Builder(Application.Context)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate)
.SetAutoCancel(true)
.SetContentIntent(PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.OneShot))
.SetContentTitle("Sample Notification")
.SetContentText("Hello World! This is my first action notification!")
.SetTicker("New Notification")
.SetSmallIcon(Resource.Drawable.icon);
// Build the notification:
Android.App.Notification notification = builder.Build();
// Get the notification manager:
NotificationManager notificationManager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;
// Publish the notification:int notificationId = ??;//This should be a real unique number, otherwise it can cause problems if there are ever multiple scheduled notifications
notificationManager.Notify(notificationId, notification);
}
}
}
Post a Comment for "Processing Notifications In Xamarin Forms Android"