Book Image

Xamarin Mobile Development for Android Cookbook

By : Matthew Leibowitz
Book Image

Xamarin Mobile Development for Android Cookbook

By: Matthew Leibowitz

Overview of this book

Xamarin is used by developers to write native iOS, Android, and Windows apps with native user interfaces and share code across multiple platforms not just on mobile devices, but on Windows, Mac OS X, and Linux. Developing apps with Xamarin.Android allows you to use and re-use your code and your skills on different platforms, making you more productive in any development. Although it’s not a write-once-run-anywhere framework, Xamarin provides native platform integration and optimizations. There is no middleware; Xamarin.Android talks directly to the system, taking your C# and F# code directly to the low levels. This book will provide you with the necessary knowledge and skills to be part of the mobile development era using C#. Covering a wide range of recipes such as creating a simple application and using device features effectively, it will be your companion to the complete application development cycle. Starting with installing the necessary tools, you will be guided on everything you need to develop an application ready to be deployed. You will learn the best practices for interacting with the device hardware, such as GPS, NFC, and Bluetooth. Furthermore, you will be able to manage multimedia resources such as photos and videos captured with the device camera, and so much more! By the end of this book, you will be able to create Android apps as a result of learning and implementing pro-level practices, techniques, and solutions. This book will ascertain a seamless and successful app building experience.
Table of Contents (20 chapters)
Xamarin Mobile Development for Android Cookbook
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Sharing code with other platforms


One of the major reasons for using Xamarin.Android is the use of C# as the programming language. But this is not the only benefit as that same C# code can be shared with other platforms, such as iOS, Windows, or Mac OS.

How to do it...

First, we are going to create the project structure that we are going to use to create our cross-platform app. In this example, we will only target Xamarin.Android and the Console, but extra platforms can be added.

  1. Open Xamarin Studio or Visual Studio and create an empty solution. For example, we are going to call this one XamarinCodeSharing.

  2. In this solution, create three projects:

    • An Android project named XamarinCodeSharing.Droid

    • A console application named XamarinCodeSharing.Desktop

    • A portable class library named XamarinCodeSharing.Core

  3. Open the project settings for XamarinCodeSharing.Core. If you are using Xamarin Studio, navigate to Build | General. Or if you are using Visual Studio, navigate to Library and then click on Change under the Targeting section.

  4. Note the various platform options available, including iOS, Android, Windows, and several others, some with version options. Ensure that the .NET4.5 and the Xamarin.Android boxes are selected as these are the platforms we are going to need.

  5. To make things easier, we are going to use a NuGet package, Microsoft.Net.Http, which simplifies the process of using HTTP and REST services. Install this package into each of the three projects.

  6. Add a project reference from XamarinCodeSharing.Droid to XamarinCodeSharing.Core and a project reference from XamarinCodeSharing.Desktop to XamarinCodeSharing.Core.

  7. Now that we have our project structure in place, we are going to write some code that will access the web service, and then see how that code is reused without modification or even recompilation. What we are going to do next all takes place in the XamarinCodeSharing.Core project.

  8. To make things easy, we can just delete the file that the IDE created. Xamarin Studio created a file named MyClass.cs, and Visual Studio created a file named Class1.cs.

  9. We can now create a new class named BlogItem, which will represent the actual blog entries. This bit is very simple and is just a set of properties:

    using System;
    
    namespace XamarinCodeSharing.Core
    {
      public class BlogItem
      {
        public string Title { get; set; }
        public string Link { get; set; }
        public DateTime PublishDate { get; set; }
        public string Description { get; set; }
      }
    }
  10. In the same project, create another new class named XamarinBlog, which both represents the blog as well as provides a means to download the blog:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    using System.Xml.Linq;
    using System.Net;
    
    namespace XamarinCodeSharing.Core {
      public class XamarinBlog {
        private const string BlogUrl = "http://blog.xamarin.com/feed";
    
        // blog metadata properties
        public string Title { get; set; }
        public string Link { get; set; }
        public List<BlogItem> Items { get; private set; }
    
        // Download the feed, parse it and return a blog object
        public static async Task<XamarinBlog> Download() {
          HttpClient client = new HttpClient();
          HttpResponseMessage response = await client.GetAsync(BlogUrl);
    
          // if all went well, read the feed, otherwise fail
          if(response.IsSuccessStatusCode) {
            return await ParseResponse(response.Content);
          }
          else {
            throw new Exception("There was a problem.");
          }
        }
    
        // Read the response out of the content and 
        // create objects
        private static async Task<XamarinBlog>ParseResponse(
        HttpContent content) {
          XamarinBlog blog = new XamarinBlog();
    
        using(Stream stream = await content.ReadAsStreamAsync()) {
          XDocument doc = XDocument.Load(stream);
          XElement channel = doc.Root.Element("channel");
    
          // load the blog metadata out of the xml
          blog.Title = WebUtility.HtmlDecode(
          channel.Element("title").Value);
          blog.Link = WebUtility.HtmlDecode(
          channel.Element("link").Value);
    
          // load the blog items out of the xml
          var items = from item in channel.Elements("item")
          select new BlogItem {
            Title = WebUtility.HtmlDecode(
            item.Element("title").Value),
            Link = WebUtility.HtmlDecode(
            item.Element("link").Value),
            PublishDate = DateTime.Parse(
            WebUtility.HtmlDecode(
            item.Element("pubDate").Value)),
            Description = WebUtility.HtmlDecode(
            item.Element("description").Value),
          };
          blog.Items = items.ToList();
        }
    
        return blog;
        }
      }
    }

    There are several important points to note here. We are using the async and await keywords to make asynchronous code easier to read, something which is not available in Java. Another feature is LINQ to XML to make working with XML easier to parse, another feature not available to Java. And finally, WebUtility.HtmlDecode is used as all the data is HTML encoded inside the XML.

Now that we have created the main logic of the app, we can look at those native implementations. First, we will create the Console app that will run on almost any desktop operating system, such as Windows, Mac OS, and most of the flavors of Linux:

  1. To do this, we can just replace the code in the Program.cs file with the following:

    using System;
    using XamarinCodeSharing.Core;
    using System.Threading.Tasks;
    
    namespace XamarinCodeSharing.Desktop {
      class MainClass {
        public static void Main(string[] args) {
          GetBlogItems().Wait();
    
          Console.WriteLine("Press any key to quit.");
          Console.ReadKey();
        }
    
        private static async Task GetBlogItems() {
          Console.WriteLine("Downloading blog...");
          XamarinBlog blog = await XamarinBlog.Download();
          Console.WriteLine("Download finished.");
          Console.WriteLine();
    
          Console.WriteLine("{0} ({1} items)",
          blog.Title, blog.Items.Count);
    
          foreach (var item in blog.Items) {
            Console.WriteLine(item.Title);
            Console.WriteLine(
              item.PublishDate.ToString("d MMMM yyyy"));
            Console.WriteLine(item.Description);
            Console.WriteLine();
          }
        }
      }
    }

If we run the desktop project now, the console will start up, download the blog feed, and then display each entry along with a short summary. Last but not least, we want to get that mobile version going. And what better platform to support first than Android?

  1. Switching to the Xamarin.Android project, we can replace the code in the MainActivity.cs file with the following:

    using System.Collections.Generic;
    using System.Linq;
    using Android.App;
    using Android.OS;
    using Android.Runtime;
    using Android.Widget;
    using XamarinCodeSharing.Core;
    
    namespace XamarinCodeSharing.Droid {
      [Activity(
        Label = "XamarinCodeSharing.Droid", 
        MainLauncher = true, 
        Icon = "@drawable/icon")]
      public class MainActivity : ListActivity {
        private const string TitleKey = "title";
        private const string SubtitleKey = "subtitle";
    
        protected async override void OnCreate(Bundle bundle) {
          base.OnCreate(bundle);
    
          var progress = new ProgressDialog(this);
          progress.SetTitle("Downloading blog...");
          progress.SetMessage(
            "Please wait while we download the Xamarin blog...");
          progress.Show();
    
          XamarinBlog blog = await XamarinBlog.Download();
          var items = from item in blog.Items select new JavaDictionary<string, object> {
            { TitleKey, item.Title },
            { SubtitleKey, item.Description }
          };
    
          ListAdapter = new SimpleAdapter(
            this,
            items.Cast<IDictionary<string, object>>().ToList(),
            Android.Resource.Layout.SimpleListItem2,
            new []{ TitleKey, SubtitleKey },
            new []{ Android.Resource.Id.Text1, Android.Resource.Id.Text2 });
    
          progress.Dismiss();
          progress.Dispose();
        }
      }
    }

If we run this Android app now, we shall get that app that downloads the latest Xamarin blog posts and displays them in a neat list.

How it works...

Portable class libraries is one of the most important aspects of code reuse. Although there are many different ways to reuse code, such as file linking or shared projects, none can match the reliability and ease of simply reusing the compiled assembly. This assembly can be tested and verified and then used and reused without fear of problems arising on different platforms.

Why? It is because each platform in each portable class library profile promises to support all the features, for all platforms, in that profile, and all those features function exactly the same.

Using Xamarin.Android, we now have all the features of the .NET runtime available, the same runtime that runs on almost all devices. Along with that same runtime, we can now build libraries that run on that runtime, and those libraries will run on all platforms that have the same runtime. Those platforms include iOS, Android, Windows Phone, Mac OS, Windows, Linux, and even more, such as PlayStation!

Although we can never achieve 100 percent code reuse, as each platform has differences (especially in the user interface), much of the code lives below the surface and can be reused. And using the commonality of the runtime and languages, we can create abstractions that can work around the platform differences, resulting in even more code reuse.

Although we only covered two platforms in this example, we can already see that it takes more code to work with the data than it does to display it. Adding extra platforms, such as Windows Phone and iOS, will result in this ultra-simple example app being able to support the major mobile operating systems, with the only difference being the UI.