Author: Konstantin Mars
When we came to
Medtech Hackathon , our goal was to create a simple and lightweight tool for users who want to keep records of first-aid kits and receive timely alerts about the expiration of their products in order to purchase new ones.
We have long hesitated with choosing a platform between the popular and prestigious iOS and fashionable, modern and pleasant in the development of Android. Therefore, I suggested using Xamarin, which, by the way, uses C # as the main development language (and this is the main language in which Arseny, our team organizer, writes in everyday life). Thus, we came to the beginning of the journey to the world of cross-platform development with Xamarin.
I note that Xamarin was originally based on the Mono framework, and therefore is somewhat different from the original Microsoft .NET framework. But we will discuss these differences a little later.
')
In the article we will not discuss the details of the hackathon and will not delve into the professional secrets of development with the help of Xamarin. This article is a basic introduction to the world of cross-platform development using Xamarin Forms. The purpose of the material is to give a general idea of ​​how to quickly develop with the help of Xamarin, to tell you where to look for answers to more specific questions in the future.
Project architecture PCL
Xamarin Forms is built around a common cross-platform code, and can be built on one of the architectural approaches - PCL (Portable Class Library) or SAP (Shared Assets Project). Platform-dependent projects are an integral part of the Xamarin solution, respectively, and are placed in a solution on a par with the common code project.
For example, in our application we have the following set of projects:
As you can see, there are projects for Android (Droid) and iOS, a separate project for AndroidWear (it is installed correctly with the Android application on the smartwatch, but does not perform any noticeable useful work, except for demonstrating the capabilities of the Xamarin framework for creating AndroidWear projects). There is also a VuforiaBindings library project (Java wrapper, which was conceived as an integrator of the Vuforia Java library for pattern and text recognition). These are examples of the key types of projects most often encountered when developing using Xamarin.
Xamarin Forms. XAML
The main advantage of developing applications with Xamarin for me is the ability to create UI for several platforms at the same time. Xamarin allows you to create separate XML forms for platform-specific projects and to make UI different for different platforms, but still the main approach is to start with Xamarin Forms, to create an XML user interface that will work equally on all supported platforms.
This became possible due to the fact that each platform-dependent project starts the code from the overall project, injecting a small piece of code specific to Xamarin Forms.
For example, in the Android project this happens in MainActivity like this:
global::Xamarin.Forms.Forms.Init (this, bundle);
In iOS project:
global::Xamarin.Forms.Forms.Init ();
At the same time, if you take a look at the MainActivity of the project for AndroidWear, you will not find there anything related to Xamarin Forms. This is because the project for this platform is not yet supported by Xamarin Forms and is a “pure” platform-dependent project written in C #.
The UI markup in Xamarin Forms is XAML. Here, everything is very similar to the “classic” .NET (WPF):
Inside XAML also looks quite familiar to those who have experience with .NET:
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand"> <Label x:Name="label" Text="List of medicines" HorizontalOptions="Center" /> <StackLayout Orientation="Horizontal"> <Entry x:Name="nameEntry" HorizontalOptions="FillAndExpand" /> <DatePicker x:Name="datePicker" HorizontalOptions="End"/> <Button x:Name="addButton" Text="Add" Clicked="add" HorizontalOptions="End" /> <Button x:Name="scanButton" Text="Scan" Clicked="scan" HorizontalOptions="End" /> </StackLayout>
The key functionality of Bindings works on the same principles as WPF bindings:
<ListView x:Name="list" VerticalOptions="FillAndExpand"> <ListView.ItemTemplate> <DataTemplate> <TextCell Text="{Binding Name}" Detail="{Binding ExpireDate, StringFormat='Expires: {0:MM-dd-yy}'}"> <TextCell.ContextActions> <MenuItem Clicked="onDelete" CommandParameter="{Binding .}" Text="Delete" IsDestructive="True" /> </TextCell.ContextActions> </TextCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
We simply place “{Binding <VARIABLE NAME>}” in the XAML instead of the hardcode values.
The main problem for Xamarin developers who work in Xamarin Studio (for example, on Mac OS) is the lack of an adequate visual UI editor. It’s strange that the studio provides developers with visual editors for specific platforms, such as Android and iOS, but, alas, not for Xamarin Forms.
DependecyService. Platform Specific Features and Xamarin Forms
When it comes time to implement something specific for the platform (for example, notifications), we can’t do without platform-specific code.
This is inevitable - after all, the same notifications are implemented quite differently for Android and iOS, and this difference is expressed in many nuances of the functional behavior. But how then to cause a similar platform-dependent code from the UI, common to all platform-dependent projects?
This is where DependencyService comes to the rescue.
As usual in cross-platform development, you need to declare the interface in a common project and implement it in platform-dependent projects. The only question is “how to determine which implementation to call in each case?”. And here DependencyService, the magic figure of the Xamarin framework, takes on the work. Depending on which platform we build the project for, DependencyService substitutes the necessary implementation instead of the interface.
It is also worth noting that in order for this magic to work, you need to use the Xamarin.Forms.Dependency annotation:
[assembly: Xamarin.Forms.Dependency (typeof (NotificationHelperImpl))]
For example, the notification interface declared in the general Xamarin Forms project looks like this:
namespace MedChestAssistant { public interface INotificationHelper { void notify(String message); } }
And the platform-dependent implementation in the Android project looks like this:
[assembly: Xamarin.Forms.Dependency (typeof (NotificationHelperImpl))] namespace MedChestAssistant.iOS { public class NotificationHelperImpl: INotificationHelper { #region INotificationHelper implementation public void notify (string message) { var notification = new UILocalNotification(); // set the fire date (the date time in which it will fire) notification.FireDate = NSDate.FromTimeIntervalSinceNow(5); // configure the alert notification.AlertAction = "Medical Chest Reminder"; notification.AlertBody = "Lyrica will expire in 2 days. Don't forget renew it"; // modify the badge notification.ApplicationIconBadgeNumber = 1; // set the sound to be the default sound notification.SoundName = UILocalNotification.DefaultSoundName; // schedule it UIApplication.SharedApplication.ScheduleLocalNotification(notification); } #endregion public NotificationHelperImpl () { } } }
In general, everything is quite simple :).
Dependencies Packages. NuGet Gallery
Xamarin has a fairly rich library of packages compatible with supported platforms - NuGet. For example, someone who needs to recognize and scan barcodes can use the Zxing package compatible with Xamarin.
After adding the package appear in the list of connected project packages.
Here, for example, is the cross-platform part of the Zxing package in our cross-platform project Xamarin Forms:
Sometimes (for example, for the Zxing library) we also need to implement some platform-specific initialization. For example, for Zxing, you need to run these lines at the start of platform-specific applications:
Android:
ZXing.Mobile.MobileBarcodeScanner.Initialize (Application);
iOS:
ZXing.Net.Mobile.Forms.iOS.Platform.Init();
Also, platform-specific initialization is also necessary for standard functionality.
For example, notifications in iOS require the declaration of supported formats at the start of the application (this is always done in the native iOS, and Xamarin simply covers the existing specifics):
if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) { var notificationSettings = UIUserNotificationSettings.GetSettingsForTypes ( UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, null ); app.RegisterUserNotificationSettings (notificationSettings); }
This is the whole overview of the development capabilities with Xamarin.
You can see the source code of our project from the hackathon here:
https://github.com/DataArt/MedChestAssistant.git
Note that this is just a code written in a short period of time on the hackathon. Therefore, only some of the basic features of Xamarin are covered. You will not find here services running in the background, complex architectural patterns, unit tests or dependency-injection, which of course will be needed in commercial projects. Our application is designed to show how to quickly and easily solve specific tasks in a short time using an excellent cross-platform tool called Xamarin.
If you want to learn more about Xamarin, refer to the official book from Microsoft
https://developer.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/
and visit the Xamarin Portal to explore the most current cross-platform development recipes
https://developer.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/
Good luck to you in the world of cross-platform! And new achievements with Xamarin! :)