📜 ⬆️ ⬇️

Cross-platform development for mobile with Xamarin

Introduction


Quite recently, Xamarin announced the release of a new version of its toolkit for cross-platform development of mobile applications, but there are still no sane articles in Russian on this topic. A small overview appeared on Habré, not related to coding, there were a couple of attempts to tell about it in a little more detail, but it didn’t go beyond the process of creating the Hello World application. It's a pity. This time we will try to correct this unfortunate misunderstanding.

Beginning of work


The installer Xamarin installs a plug-in to Visual Studio, which allows you to develop applications for popular mobile platforms in a familiar developer environment. A separate development environment Xamarin Studio is also being installed, which, apparently, is a modified version of MonoDevelop. I’m used to working in Visual Studio so the examples in this article will be shown using this particular development environment.

After installation, project templates for mobile applications for Android and iOS are added to Visual Studio (it supports the creation of both specialized applications for iPad and iPhone, universal applications, and applications using OpenGL). To create applications for iOS in Visual Studio will have to, however, pay. This functionality is available either in trial mode or in the business version of the toolkit, and it costs $ 999 per year.

After creating the project, we get the same API for each platform that we have in native development, but the syntax will be in C #, besides, it is possible to use the basic types of the .NET Framework, syntax sugar and other .NET buns.
')

Android development


After creating the Android project, we get a set of files in which there is a class of the main window and a set of resource files. After long work in Eclipse, the name of the folders in PascalCase is a bit annoying, but you can get used to it rather quickly. There are also differences in working with resource files. In order for the embedded window designer to understand resource files with layouts, their extension has been changed to .AXML instead of the usual .XML in Eclipse. This is pretty annoying, especially if you draw layouts in Eclipse, and then transfer them to Visual Studio in case Eclipse's window designer is more like it.

The built-in window designer seemed to me inconvenient. Slow, often brings down the whole IDE, I still do not understand how it is easy to switch between the XML-type and UI. Here we can definitely say that it was written by strangers for predators. I decided for myself that in Eclipse it is more convenient for me, more familiar, and more useful information is placed on the laptop screen in Eclipse. Maybe someone designer Visual Studio and enjoy it more, the taste and color markers are different.

Activities

C # code for Mono for Android is very similar to Java code.
namespace XamarinDemo.Android { [Activity(Label = "XamarinDemo.Android", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { int count = 1; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); Button button = FindViewById<Button>(Resource.Id.MyButton); button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); }; } } } 

Differences that are immediately visible:


Controls and Event Handling

To get references to controls, as in the Java version, use the FindViewById() method. Very pleased with the presence of a generic version of this method, which returns an object of the desired type and allows you to get rid of c-Cast'ov.
Instead of listeners, or rather, in addition to them, delegates are used to connect event handlers. You can also use listeners, but this is, firstly, not the .NET way, and secondly, it requires writing more code, even compared to Java. In addition, several delegates can be connected:
 Button button = FindViewById<Button>(Resource.Id.MyButton); button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); }; button.Click += (o, e) => { Toast.MakeText(this, string.Format("{0} clicks!", count++), ToastLength.Long).Show(); }; 

Not with all event handlers in the form of delegates things are rosy. One of the projects revealed a problem with the View.ViewTreeObserver.GlobalLayout event, which did not disable handler delegates when using the - = operator. Yes, in general, did not turn off. I had to use IOnGlobalLayoutListener .

Using Java libraries in a .NET project

Mono for Android has the ability to use existing JAR files in a C # application. For these purposes, a special project type is provided: Java Binding Library.
To use the JAR library, you must:

After that, you can use classes from a JAR file. Be aware that package names in C # and in Java source code may differ slightly. For example, the com.example.androiddemolib package from Java code will be renamed to Com.Example.Androiddemolib (that is, it will be converted to PascalCase).
A good guide to using Java libraries can be found here .

Work with databases

Mono for Android uses the Mono.Data.Sqlite namespace Mono.Data.Sqlite (used to access SQLite databases) and System.Data.SqlClient (for accessing Microsoft SQL Server) to work with databases. The classes of the System.Data.SqlClient namespace are available only in the Business edition of the development tools. You can also use wrapper classes over native Java API for Android and third-party development, such as sqlite-net, in which an asynchronous API is available.
Using the available API is quite simple. Everything is very similar to desktop development:
 namespace XamarinDemo.Android { [Activity(Label = "XamarinDemo.Android", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { SqliteConnection GetConnection(string path) { SqliteConnectionStringBuilder builder = new SqliteConnectionStringBuilder(); if (!File.Exists(path)) { FileInfo info = new FileInfo(path); if (!Directory.Exists(info.Directory.FullName)) { Directory.CreateDirectory(info.Directory.FullName); } SqliteConnection.CreateFile(path); } builder.DataSource = path; return new SqliteConnection(builder.ToString()); } protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); try { string path = GetDatabasePath("xamarindemo.sqlite").Path; SqliteConnection connection = GetConnection(path); connection.Open(); SqliteCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = "CREATE TABLE IF NOT EXISTS DemoTable(" + "id INTEGER AUTO_INCREMENT PRIMARY KEY NOT NULL" + ", name VARCHAR(32))"; command.ExecuteNonQuery(); connection.Close(); } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.ToString()); } } } } 


IOS development



Controls and Event Handlers

Creating controls in code is no different from analogous work in Objective-C. Event handlers can be hung in the same way as in Android - with the help of delegates. You can also add handlers as in Objective-C through selectors.
 namespace XamarinDemo.iOS { public class MyViewController : UIViewController { UIButton button; … public MyViewController() { } public override void ViewDidLoad() { base.ViewDidLoad(); … button = UIButton.FromType(UIButtonType.RoundedRect); … button.AddTarget(this, new Selector("ButtonTouchInside"), UIControlEvent.TouchUpInside); … button.TouchUpInside += (object sender, EventArgs e) => { button.SetTitle(String.Format( "clicked {0} times", numClicks++), UIControlState.Normal); }; … View.AddSubview(button); } [Export("ButtonTouchInside")] void OnButtonTouchInside() { Console.WriteLine("Hello!"); } } } 


Using Native Libraries

In Xamarin iOS, as well as for Android, the ability to use native libraries is available. For these purposes, there is a special type of project - the iOS Binding Project, to which you can add static libraries, after which they will be linked together with the main project.

In general, to use a native library in a C # project, you need to do the following:

In general, it is very good and accessible about binding native libraries written here .

Work with databases

To work with databases in iOS, the same namespaces are used as in Android. The API, respectively, is the same. A small difference can be in the details. For example, to get the path to the SQLite database file on Android, there is a special API call:
 string path = GetDatabasePath("xamarindemo.sqlite").Path; 

In iOS, you need to use the standard .NET tools:
 string path = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Personal), "xamarindemo.sqlite"); 


Remote debugging of iOS applications from Visual Studio

In Xamarin 2.0, you can debug mobile apps for iOS right from Visual Studio. In order to make this possible, you need to have Macs with XCode, iOS SDK and Xamarin Studio installed on the local network. You do not need to make any additional settings; it’s enough when you open an iOS project in Visual Studio to select the required build server from the list of available ones.

Unfortunately, this approach did not work with a virtual machine running on the same computer as Visual Studio. Although everything works fine with a regular Mac on a local network. I could not find any reasons or explanations for this, I try to communicate with the developers about this.

It is also not very clear how to organize UI testing and application health check from Visual Studio. The simulator runs on a Mac, it seems that VNC is indispensable here.

Cross Platform Class Libraries (Portable Class Libraries)


Xamarin provide the ability to create libraries that can be used (in the form of code or ready-made assemblies) for several platforms at once. Such libraries are called Portable Class Library (PCL).

For the development of such libraries, a special truncated version of the .NET Runtime is used and this is a wonderful tool for the developer, the importance of which is difficult to overestimate, but here, too, everything is not so simple. By default, Visual Studio cannot specify Android and iOS as supported platforms for the PCL project. But this does not mean that Visual Studio immediately becomes useless in this regard.

The problem can be solved by creating XML files in the folder C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile104\SupportedFrameworks for x64 systems or in the folder C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile104\SupportedFrameworks for x86 systems.
Android file MonoAndroid, Version = v1.6 + .xml
 <?xml version="1.0" encoding="utf-8"?> <Framework DisplayName="Mono for Android" Identifier="MonoAndroid" Profile="*" MinimumVersion="1.6" MaximumVersion="*" /> 

iOS VSMonoTouch file , Version = v1.0 + .xml
 <?xml version="1.0" encoding="utf-8"?> <Framework DisplayName="VS MonoTouch" Identifier=".NETFramework" Profile="*" MinimumVersion="1.0" MaximumVersion="1.0" /> 

After creating these two files and restarting Visual Studio, you can specify Android and iOS as supported platforms for new PCL projects or add these platforms to existing projects via Properties -> Library -> Target Framework.
But this is not all the nuances.

If you want support for Android and iOS in a PCL project, then you will have to abandon support for Xbox 360 and Windows Phone 7 (but you can support Windows Phone 7.5+). For Xbox, you will have to create another project and add files from the existing PCL project as links. Or, as an option, leave all Microsoft platforms (including Xbox 360) in one PCL project, and only iOS and Android in the other.

There is still such a problem that a PCL project added from Visual Studio for Windows will not participate in the solution build if you open it in Xamarin Studio under OS X. The project will be inactive and a message will be displayed (not built in active configuration) . This problem is solved by removing the project from the solution and adding it again.

New language features and support for C # 5


In the development for Android, it is important to transfer work with files, databases, network, etc., that is, with long-term operations, into a separate stream. C # 5 provides special capabilities for implementing asynchronous operations, namely async / await . Unfortunately, in the current version of Mono for Android and MonoTouch these features are not available. Because of this, many quite interesting libraries cannot be used in the form that is provided for them. For example, to work with the asynchronous API of the sqlite-net library, you have to do several tricks with your ears. The good news is that these features should become available in a few months with the transition from Xamarin to C # 5.

Additional components and libraries


Xamarin, in addition, in fact, sales of software development tools, opened a store selling third-party components, many of which really greatly simplify the life of the developer. The store has both paid and free libraries and themes. The usefulness, for example, of free Xamarin.Auth , Xamarin.Social and Xamarin.Mobile is difficult to overestimate. It is possible to publish your own components in this store.

Unpleasant moments


Of the problem points, the most noticeable are:


Pleasant moments




findings


The Xamarin toolkit does yes, it really works and if you plan to develop several applications a year or the planned profit from the application being developed is more than $ 2k, then the Xamarin SDK can clearly make your life easier and save you from duplicate work on the code for each platform.

On the other hand, for the Indy-developer, the price of $ 1k for each platform, for example, seems to me excessive because There are many nuances that you need to know and / or feel for yourself before starting development, there are bugs that are not known in which mode they will be fixed and it is not known how much their presence can slow down the development of your particular project.

A little cool ssylochek!




UPD: Updating from northicewind about the cost of the license:
The license is perpetual, but includes one year of free updates. I wrote to them in support for explanations. Here is their answer
Your license is perpetual. You have to purchase a renewal every year to get new updates.

Source: https://habr.com/ru/post/172121/


All Articles