Slide 1

Slide 1 text

Cross-platform Mobile Applications with C# and .NET NEBytes User Group 15th August 2012

Slide 2

Slide 2 text

Chris Hardy • C# Contractor • Work with Xamarin • Write some books • First spoke about MonoTouch in January 2010 • http://twitter.com/chrisntr

Slide 3

Slide 3 text

What is Mono? • Open source implementation of the .NET platform, based on ECMA 334/335 • 2001: Created to bring Windows applications to Linux • 2003: Acquired by Novell with Ximian • Matured at Novell in research mode; now a world-class runtime.

Slide 4

Slide 4 text

C# IronRuby IronPython Visual Basic F#

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

May 2011: Attachmate • May 2nd: Attachmate buys Novell - Mono team laid off • Xamarin founded 2 weeks later • Angry Mono customers pressure Novell to cooperate with Xamarin • Xamarin secures a perpetual license to all Mono IP: copyrights, patents and trademarks

Slide 7

Slide 7 text

C# IronRuby IronPython Visual Basic F#

Slide 8

Slide 8 text

Xamarin

Slide 9

Slide 9 text

Xamarin • Team of around 47 people • Over 150,000 downloads • Over 7,500 paid users • $12m Series A investment

Slide 10

Slide 10 text

MonoTouch

Slide 11

Slide 11 text

What is MonoTouch? • C# on iOS devices (iPhone, iPod Touch, iPads) What MonoTouch is not... • Silverlight for iOS devices • Compact Framework for iOS devices • iOS development without a Mac • A meta-platform

Slide 12

Slide 12 text

xamarin.com/apps/all

Slide 13

Slide 13 text

Commercial Product • Free for Simulator-only • $399 for Professional License (Requires Apple Dev License) • $999 for Enterprise License (Requires Apple Dev License Pro/Ent) • $2499 for Enterprise Priority License (Requires Apple Dev License Pro/Ent)

Slide 14

Slide 14 text

Demo Tweeting with MonoTouch

Slide 15

Slide 15 text

MonoTouch APIs .NET APIs Native APIs 3rd Party mscorlib System System.Core (LINQ) System.Data Mono.Data.Sqlite System.ServiceModel System.Json System.Web.Services (WCF) System.Xml System.Xml.Linq AddressBook/ AddressBookUI AudioToolbox/ AVFoundation CoreAnimation CoreGraphics CoreLocation EventKit/EventKitUI ExternalAccessory GameKit MapKit NewsstandKit StoreKit Twitter UIKit And so on.... OpenTK OpenGL OpenAL SQLite MonoGame RestSharp Json.NET ServiceStack Steema TeeChart Flurry Analytics RedLaser And so on...

Slide 16

Slide 16 text

Strong Types • Objective-C Arrays are weakly typed: NSArray return values. • MonoTouch has strong types: UIView[] Subviews { get; } vs NSArray *subviews; • Code Completion - explore the API...

Slide 17

Slide 17 text

MonoTouch Events • Supports Objective-C pattern (including blocks): webView.Delegate = new MyWebViewDelegate(); • C# style events as well: webView.PageLoaded += delegate { HideSpinningWheel(); }

Slide 18

Slide 18 text

Garbage Collection x2 • Automatic: • Mono’s GC will collect objects on demand • Deterministic: • Use when you need control. • Every object in MonoTouch implements IDisposable using (var image = UIImage.FromFile(“foo.png”)){ surface.DrawImage(image, 20, 20); }

Slide 19

Slide 19 text

MonoTouch Designer Integration • Integrates with Interface Builder inside of Xcode 4 • Supports Storyboards

Slide 20

Slide 20 text

Demo Xcode Integration

Slide 21

Slide 21 text

Using Third Party Libraries

Slide 22

Slide 22 text

Objective-C Library • Download the .a static library and header file • Run parse/btouch command to create a self contained .dll • Add reference to the project • Include any resources that are required

Slide 23

Slide 23 text

Rebuild your libraries • Can’t just use any DLL • Re-compile for each lib • Each framework has its own class library .NET Libraries

Slide 24

Slide 24 text

Mono for Android

Slide 25

Slide 25 text

What is Mono for Android? • C# on Android devices What Mono for Android is not... • Silverlight for Android devices • Compact Framework for Android devices • Supported for Linux • A meta-platform

Slide 26

Slide 26 text

xamarin.com/apps/all

Slide 27

Slide 27 text

• Available on Windows and Mac • First-class VS 2010 Support • MonoDevelop on Windows and Mac • JIT (Just in Time compilation) • Potential to support all .NET languages • Shared Runtime for Development • APK for release includes Mono + Linked Assemblies Mono for Android

Slide 28

Slide 28 text

Mono for Android Architecture

Slide 29

Slide 29 text

Mono for Android APIs .NET APIs Native APIs 3rd Party mscorlib System System.Core (LINQ) System.Data Mono.Data.Sqlite System.ServiceModel System.Json System.Web.Services (WCF) System.Xml System.Xml.Linq Android.Accounts Android.App.* Android.Bluetooth Android.Content.* Android.Database Android.Graphics Android.Hardware Android.Locations Android.Net.* Android.Nfc Android.Text Android.Util Android.Views.* Android.Widget Java.Lang.* Java.Util.* And so on.... OpenTK OpenGL OpenAL SQLite MonoGame RestSharp Json.NET ServiceStack Steema TeeChart And so on...

Slide 30

Slide 30 text

Commercial Product • Free for Simulator-only • $399 for Professional License • $999 for Enterprise License • $2499 for Enterprise Priority License

Slide 31

Slide 31 text

Xamarin Designer for Android

Slide 32

Slide 32 text

Xamarin Designer for Android

Slide 33

Slide 33 text

x86 Emulator Support • Much faster deployment • Debugging is almost instant • Only supported on Intel • Provided by Google

Slide 34

Slide 34 text

Demo Mono for Android

Slide 35

Slide 35 text

MonoTouch and Mono for Android Features

Slide 36

Slide 36 text

Features • MonoDevelop iPhone/Android Add-In • Visual Studio support for Android • monotouch.dll / monoandroid.dll • Full static AOT compiler / Allow JIT for Android • Support for all your existing code • Reflection • Generics • LINQ • Anonymous Methods • Lambda’s etc...

Slide 37

Slide 37 text

Linker and the application size...

Slide 38

Slide 38 text

What about App Size? • 50 MB (compressed) limit on 3G/Edge downloads • .Net BCL and other libraries are huge • Mono Linker to the rescue!

Slide 39

Slide 39 text

Linking Assemblies

Slide 40

Slide 40 text

What about App Size? • iOS - ~2.6MB Compressed...ish • Android - ~2.6MB Compressed...ish

Slide 41

Slide 41 text

Cross platform with MonoTouch, Mono for Android, WP7

Slide 42

Slide 42 text

Win/WP7 WPF Silverlight OSX MonoMac C# Plus ECMA languages .NET iOS MonoTouch Android Mono for Android Mono Business Logic and Middleware (engine, core and 3rd party) Native UI APIs Runtime OS Code sharing and native experience

Slide 43

Slide 43 text

MWC 2012 http://bit.ly/mwc2012xamarin

Slide 44

Slide 44 text

MWC 2012 • 1,635 Lines of shared code - 771 for ORM • iPhone + iPad (2,476 LOC / 2 Apps) - 57% Re-use • Android (1,095 LOC) - 60% Re-use • Windows Phone 7 (896 LOC) - 65% Re-use

Slide 45

Slide 45 text

Techniques for Cross Platform Code 1. Portable Library Tools 2. Linking Files 3. Project Linker 4. Xamarin.Mobile

Slide 46

Slide 46 text

Portable Library Tools http://bit.ly/portablelibrarytools

Slide 47

Slide 47 text

Portable Library Tools • Pros • One class library to rule them all • Common subset across all platforms • Cons • No Pre-processor Directives • No platform specific-code • Limited API set - no System.Xml.Linq or System.Net.WebClient

Slide 48

Slide 48 text

Demo Telephone Converter

Slide 49

Slide 49 text

Linking Files

Slide 50

Slide 50 text

Demo Twitter App

Slide 51

Slide 51 text

Project Linker http://bit.ly/projectlinkervs

Slide 52

Slide 52 text

Project Linker • Pros • Auto-link files between projects • Cons • Does not work with MonoDevelop • Must have all projects in the same solution

Slide 53

Slide 53 text

Xamarin.Mobile

Slide 54

Slide 54 text

http://xamarin.com/mobileapi

Slide 55

Slide 55 text

StringBuilder builder = new StringBuilder(); String lineSep = System.getProperty("line.separator"); ContentResolver content = getContentResolver(); Cursor ncursor = null; try { ncursor = content.query (ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.Data.MIMETYPE, ContactsContract.Contacts.LOOKUP_KEY, ContactsContract.Contacts.DISPLAY_NAME }, ContactsContract.Data.MIMETYPE + "=? AND " + ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME + "=?", new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, "Eric" }, null); while (ncursor.moveToNext()) { builder.append (ncursor.getString(ncursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)) + lineSep); String lookupKey = ncursor.getString (ncursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); Cursor dcursor = null; try { dcursor = content.query (ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.Data.DATA1 }, ContactsContract.Contacts.LOOKUP_KEY + "=?", new String[] { lookupKey }, null); while (dcursor.moveToNext()) { String type = dcursor.getString (ncursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); if (type.equals (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) builder.append ("Phone: " + dcursor.getString(dcursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)) + lineSep); else if (type.equals (ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) builder.append ("Email: " + dcursor.getString(dcursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA1)) + lineSep); } builder.append(lineSep); } finally { if (dcursor != null) dcursor.close(); } } } finally { if (ncursor != null) ncursor.close(); } t.setText(builder.toString());

Slide 56

Slide 56 text

var builder = new StringBuilder(); var abook = new AddressBook(this); foreach (Contact c in abook.Where (c => c.FirstName == "Eric" && c.Phones.Any())) { builder.AppendLine (c.DisplayName); foreach (Phone p in c.Phones) builder.AppendLine (String.Format ("{0}: {1}", p.Label, p.Number)); builder.AppendLine(); } Console.WriteLine (builder.ToString());

Slide 57

Slide 57 text

StringBuilder builder = new StringBuilder(); String lineSep = System.getProperty("line.separator"); ContentResolver content = getContentResolver(); Cursor ncursor = null; try { ncursor = content.query (ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.Data.MIMETYPE, ContactsContract.Contacts.LOOKUP_KEY, ContactsContract.Contacts.DISPLAY_NAME }, ContactsContract.Data.MIMETYPE + "=? AND " + ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME + "=?", new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, "Eric" }, null); while (ncursor.moveToNext()) { builder.append (ncursor.getString(ncursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)) + lineSep); String lookupKey = ncursor.getString (ncursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); Cursor dcursor = null; try { dcursor = content.query (ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.Data.DATA1 }, ContactsContract.Contacts.LOOKUP_KEY + "=?", new String[] { lookupKey }, null); while (dcursor.moveToNext()) { String type = dcursor.getString (ncursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); if (type.equals (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) builder.append ("Phone: " + dcursor.getString(dcursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)) + lineSep); else if (type.equals (ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) builder.append ("Email: " + dcursor.getString(dcursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA1)) + lineSep); } builder.append(lineSep); } finally { if (dcursor != null) dcursor.close(); } } } finally { if (ncursor != null) ncursor.close(); } t.setText(builder.toString()); Manually in Java

Slide 58

Slide 58 text

var builder = new StringBuilder(); var abook = new AddressBook(this); foreach (Contact c in abook.Where (c => c.FirstName == "Eric" && c.Phones.Any())) { builder.AppendLine (c.DisplayName); foreach (Phone p in c.Phones) builder.AppendLine (String.Format ("{0}: {1}", p.Label, p.Number)); builder.AppendLine(); } Console.WriteLine (builder.ToString()); Xamarin.Mobile for Android

Slide 59

Slide 59 text

var builder = new StringBuilder(); var abook = new AddressBook(); foreach (Contact c in abook.Where (c => c.FirstName == "Eric" && c.Phones.Any())) { builder.AppendLine (c.DisplayName); foreach (Phone p in c.Phones) builder.AppendLine (String.Format ("{0}: {1}", p.Label, p.Number)); builder.AppendLine(); } Console.WriteLine (builder.ToString()); Xamarin.Mobile for iOS

Slide 60

Slide 60 text

var builder = new StringBuilder(); var abook = new AddressBook(); foreach (Contact c in abook.Where (c => c.FirstName == "Eric" && c.Phones.Any())) { builder.AppendLine (c.DisplayName); foreach (Phone p in c.Phones) builder.AppendLine (String.Format ("{0}: {1}", p.Label, p.Number)); builder.AppendLine(); } Console.WriteLine (builder.ToString()); Xamarin.Mobile for Windows Phone 7.1

Slide 61

Slide 61 text

Taking this further MonoCross MVVMCross

Slide 62

Slide 62 text

MonoCross • MVC framework where Model and Controller are shared • Open Source (MIT License) • Views are native to the individual platform • www.monocross.net

Slide 63

Slide 63 text

MVVMCross • MonoCross for MVVM pattern • Open Source (MS-PL) • Separation of Concerns • Designability/Testability • Cross-platform code re-use • github.com/slodge/MvvmCross

Slide 64

Slide 64 text

More resources? • http://docs.xamarin.com • Forums / Mailing Lists • StackOverflow • contact@xamarin.com • twitter.com/xamarinhq

Slide 65

Slide 65 text

Creating amazing applications!

Slide 66

Slide 66 text

Q & A Thanks!