Using the new iOS 10 UserNotification framework in Xamarin.iOS
Apple recently introduced a new notification API in iOS 10 that allows for much richer experience. These new notifications allow deeper customizations to the notification content including the ability to add images and gifs to your local and remote notifications. The UserNotification framework replaces the previous notification system, and unifies app notifications for Apple's different OS's. In this article we'll take a look at using the new framework with Xamarin.iOS by creating a notification that uses the GetImage method of FlexChart to embed an image of your chart into a notification.
The UserNotification framework
The new UserNotification framework handles both local and remote notifications, and replaces the previous NSNotifications which Apple has used in recent years. It provides a powerful new method of creating notifications based on a triggers which you can define in your code. It also adds more possibilities for you notifications by easily adding image attachments and even embedding custom view controllers into your notifications. This of course requires that you spend some time learning the new API. Thankfully, Apple has a lot of documentation available on it's site. Xamarin also provides some basic getting started guides.
Getting Started
The first step for working with the UserNotification framework is to add Using statement to the top of your AppDelegate and ViewController.
using UserNotifications;
After that's done we'll need to request permission from the user to display our notification. This is most easily done in the FinishedLaunching method of your AppDelegate.
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
// Override point for customization after application launch.
UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
{
// You can add further code here to handle approval
});
return true;
}
This will prompt a user for permission to send notifications the first time that they use your app. The ViewController doesn't deviate too much from any of the other Xuni samples except in one or two areas. We are going to call a Notify() method (which we'll get to later) that sets up the notification at the end of ViewDidLoad(). You'll also notice we're going to use the ViewDidAppear method to capture and save a local image of the FlexChart that we'll be using for the notification. The reason this is done in ViewDidAppear is to ensure that we're capturing the populated chart rather than an empty one. The local image we'll later use in the notification.
namespace NotificationChart
{
public partial class ViewController : UIViewController
{
private FlexChart chart;
private FlexChartDataSource ds;
protected ViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
Xuni.iOS.Core.XuniLicenseManager.Key = License.Key;
chart = new FlexChart();
chart.Frame = this.View.Frame;
ds = new FlexChartDataSource();
chart.BindingX = "name";
chart.Series.Add(new Series(chart, "Sales", "Sales"));
chart.ItemsSource = ds.Data;
chart.IsAnimated = false;
this.View.AddSubview(chart);
Notify();
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
chart.Frame = this.View.Frame;
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
//this is where we create and save the image of the chart after it's been generated.
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string fileName = Path.Combine(documents, "image.png");
File.WriteAllBytes(fileName, chart.GetImage().ToArray());
}
...
The Notify() method is where we'll actually put the notification together. We'll create objects to handle the content and options for our notificiation. The content gives you a number of options for configuring your notificaiton including title, subtitle, body text, badge, and any attachments (such as our chart image). Once that's set up we need to set a trigger for our notification to determine when it will occur initially and whether it's recurring. For our example we'll set it to go off after 60 seconds and choose not for it to recur.
public void Notify()
{
//the logic for our actual Notification
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string fileName = "file:///" + Path.Combine(documents, "image.png");
NSUrl url = NSUrl.FromString(fileName);
var attachmentID = "image.png";
var options = new UNNotificationAttachmentOptions();
var content = new UNMutableNotificationContent();
content.Title = "Xuni";
content.Subtitle = "FlexChart";
content.Body = "Your most recent sales data.";
content.Badge = 1;
NSError error;
var attachment = UNNotificationAttachment.FromIdentifier(attachmentID, url, options, out error);
content.Attachments = new UNNotificationAttachment[] { attachment };
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(60, false);
var requestID = "sampleRequest";
var request = UNNotificationRequest.FromIdentifier(requestID, content, trigger);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
// Throw an error...
}
});
}
You'll now notice that a notification will now fire when your app isn't active.
Rounding things out
That's the extent of what it takes to work with the UserNotification framework. There are deeper customizations available, and, while we've focused on local notifications, remote notifications are another possibility. In the future we'll take a further look at some other notification possibilities, as well as check out some of the recent changes on Android.