Showing posts with label monotouch. Show all posts
Showing posts with label monotouch. Show all posts

Tuesday, 29 September 2015

iOS 9-ify your Xamarin.Forms App

It's not just regular Xamarin.iOS apps that can implement fancy iOS 9 features :) Check out the quick hacks I did to this Restaurant Guide Xamarin.Forms sample to add iOS 9 features:





Mostly using the magic of Dependency Service I added:


No special work was required to get the app running with iPad Multitasking, other than to ensure there was a Storyboard (or XIB) Launchscreen.



Finally, I added the Application Transport Security "opt-out" tags to the Info.plist file, so that the links to all the different restaurants would work in the WebView control.

Download the code from github to try for yourself!

p.s. Ignore the fact that this sample uses Razor templates to generate the restaurant detail view. That is merely a coincidence - this existing Xamarin.Forms sample was the most appropriate to add iOS 9 features to. iOS 9 features can be added to any Xamarin.Forms app, whether it displays data with XAML, C#, or in a Razor HTML template ;)

Sunday, 27 September 2015

iOS 9-ify your Xamarin App

With the iPhone 6s models now available, it's possible to build and test all the great new features of iOS 9 with Xamarin. To demonstrate, I've tried to squeeze as many iOS 9 features as possible into one sample: To9o app (that's "Todo" but with a "9" :-) The c# code is on github and screenshots of each iOS 9 feature are shown below.

3D Touch

3D Touch can used a few different ways, but requires an iPhone 6s to test (the Simulator doesn't support 3D Touch). I started by adding these two:

Multitasking for iPad

If the app can resize its UI appropriately, it should work fine for multi-tasking!

ContactsUI

The "Todo" app doesn't traditionally need an interface to the Contacts list, but I added it just to give this new API a try :)

New Search APIs

The new search APIs let you expose content to search and Siri. I've added both:
Notice the Back to Search button in the navigation bar.

UIStackView

This new layout option makes it much easier to build screens that 'scale', and also makes it even easier to support RTL languages (see below).
* Note: currently UIStackViews must be drawn using Xamarin's Xcode integration, but the built-in Xamarin iOS Designer will support them soon!

Collection View Changes

The main Todo list is a UICollectionView rather than a table, so it can demonstrate how easy it now is to re-order items with two simple methods added in code.

Right-to-Left Language Support

The entire app can now automatically flip (including UINavigationController animations) when displaying RTL languages like Arabic and Hebrew (note: machine translation used for example, apologies for any inaccuracies).

SFSafariViewController

This new API makes it easy to implement an in-app web browsing experience with a line or two of code. I've used it just for an "About" window.



All these improvements are explained in Xamarin's iOS 9 docs, and the code is available to review. It is still a work-in-progress so check back for more updates. 

Tuesday, 15 January 2013

Xamarin for Java Developers

Last night I was given the opportunity to present Xamarin's Mono for Android to the East Bay Google Developer Group. It was a lot of fun, with plenty of the audience asking a lot of great questions and generally being curious about how C# can be used to build Android apps. Here are the slides from the talk - please drop me a line with any feedback or questions!

One topical question was "what does using Xamarin and C# offer existing Android Java developers?". I have a couple of thoughts which are listed below (in no particular order):

Learn a new language!
The days of specializing in a single language throughout your career (or even throughout the year!) are over. Once upon a time it was COBOL all the way down, and you could argue that it's still enough to just know C/C++. But it's no longer the norm ~ developers want to grow and learn, and use the best tool for the job (whether it's Perl, PHP, Java, Ruby, C#, F#, Javascript, TypeScript, Go, or whatever).

It can be daunting though, to start from scratch and learn a new IDE, framework and syntax - which is why I think C# is a great progression for Java devs. The two languages are obviously related - there is a lot of common syntax and equivalent keywords that make it easy to get proficient quickly. They're both strongly typed, so the IDE and compiler can really help you learn. Then once you know the C# basics, a whole world of new APIs open up to you: LINQ, the .NET framework's serialization and web service features, Parallel Task Library and async support, reactive extensions, and more.

It also introduces you to another IDE (Visual Studio is a great tool, as is Xamarin's free MonoDevelop IDE), which in turn can encourage you to further explore other languages and platforms (suddenly it's a small leap to work on Windows Phone, or try F#). Using the free trial you can easily get productive in C# and Android development without any up-front cost: you can run your apps on the Android emulator, and choose to work on either Windows or Mac with MonoDevelop.

Cross-platform development!
There are a lot of Java developers who are already proficient with the Android SDK and have published successful apps to Google Play, or Amazon, or Samsung app stores; and there's another group of corporate/enterprise developers building apps for internal/extranet use that were designed for Android. When these developers ask "why Xamarin?", I never say "throw away everything you've done and re-write in C#!" -- that'd be crazy ;-)

But what happens when you want to take these apps cross-platform, either to make more money on the iOS and Mac App Stores or to better support a corporate BYOD policy which means your internal apps need to run on iOS and Windows? You can choose to learn Objective-C to write for iOS and C# for Windows... or take the opportunity provided by Xamarin to use C# for all the non-Java platforms and reduce the amount of code you have to support and re-write by half!

Following on from the first point, I think learning C# is a much smaller leap for a Java developer than Objective-C; and once you've done so you can work on either iOS apps using Xamarin's MonoTouch or Windows Phone, Windows 8 and Windows RT tablet apps! You might like C# so much that you do go back and re-write your Java, or at least start building a hybrid that shares some Java and C# code...

Xamarin does Android well too :)
If Java developers do fall in love with C# then they also find that Xamarin does Android just as well as anyone (probably better!). Our MonoDevelop IDE (and our integration with Visual Studio) means you get an awesome coding experience (autocomplete/intellisense/code completion, debugging, refactoring, source control integration, etc) as well as a drag-and-drop UI designer. You be the judge of whether it's a better experience than Eclipse :)

Fin
In summary, why not? As a Java developer you have a lot to gain and nothing to lose by giving C# a try. A whole world of new platforms, tools and frameworks become available with a very low barrier to entry. Try it - you just might like it ;-)

Thursday, 3 January 2013

Localizing iOS6 Storyboards with MonoTouch

Localization and internationalization of XIB and Storyboard files has historically been a very manual process. Typically these file types would be duplicated in each 'language directory' (*.lproj) and then the text and layout tweaked independently by each translator. Changes to the actual Storyboard or XIBs would need to be manually propagated across all the 'language copies'.

In iOS6 Apple introduced a new concept - Base Localization - which you can read about in their documentation on Internationalizing Your App. Your project can contain a 'special' Base.lproj directory where the Storyboard files are located, and then a corresponding *.strings file (whose filename matches the Storyboard's) in each language directory with the translations.

There is a small sample showing how this works with MonoTouch - TaskyL10nStoryboard on github. There is no IDE support currently, but you can easily create the Base.lproj directory manually in MonoDevelop and everything works as expected. Here's a screenshot of the project structure:

then inside the Storyboard itself you need to identify the controls you wish to localize. Click on a control to discover its Object ID, and shown in this screenshot:

Using the Object IDs from the Storyboard file, we can translate the display values for various properties (including text, placeholders and others) in the MainStoryboard.strings file in each language directory, like this:
"SXg-TT-IwM.placeholder" = "nombre de la tarea";
"Pqa-aa-ury.placeholder"= "otra información de tarea";
"zwR-D9-hM1.text" = "Detalles de la tarea";
"bAM-2j-Rzw.text" = "Notas";
"NF3-h8-xmR.text" = "Completo";
"MWt-Ya-pMf.normalTitle" = "Guardar";
"IGr-pR-05L.normalTitle" = "Eliminar";
Using the Object ID and property as the localization key is quite different to Apple's previous guidance on localization, where the key is typically the base-language's actual displayable value.

Here's the localized Storyboard, in Japanese:


What about layout?
Strings can often be very different lengths in different languages. When you used a different Storyboard or XIB for each language then the control sizes could be manually adjusted to fit. When using Base Localization you should use Apple's new constraint-based layout to handle these size differences.

What about iOS5 and earlier?
This method only works on iOS6. To localize text on earlier versions of iOS you will have to duplicate your Storyboards and XIBs for each language, or create outlets for all the controls and set their localized text values in code using NSBundle.MainBundle.LocalizedString().
There is another localized sample - TaskyL10n - which shows how to localize text elements directly and uses MonoTouch.Dialog.

Sunday, 23 September 2012

iOS 6 UIRefreshControl with MonoTouch

Another cute little new feature of iOS 6 is the built-in pull-to-refresh control - UIRefreshControl. It is really simple to wire up with Xamarin on a regular UITableViewController or with MonoTouch.Dialog.

In case you're unfamiliar with it, this is how the new control looks:

To implement:

  • Assign the RefreshControl property of a UITableViewController to a new instance of the control, eg. RefreshControl = new UIRefreshControl();
  • Create a handler for the control's ValueChanged event, eg RefreshControl.ValueChanged += HandleValueChanged;. In this handler your code will do whatever is required to refresh the data when the user pulls down enough to trigger the event.
  • In HandleValueChanged code, once you have refreshed the table, call the EndRefreshing method of the control to stop it spinning. Your refresh code was probably not running on the main thread, in which case you'll probably want to use InvokeOnMainThread like this: InvokeOnMainThread (() => {RefreshControl.EndRefreshing (); });

There are additional features you may use:

  • BeginRefreshing - call this method from your code if you start a refresh operation from code (eg. on a timer or in response to some other event). This sets the UI of the control to indicate there is already a refresh in progress.
  • Refreshing - whether there is already a refresh in progress.
  • AttributedTitle - optional text that appears under the refresh control.
  • TintColor - customize the appearance of the control to match your application's theme.

Refer to Apple's UIRefreshControl doc for additional info.

UPDATE: What about iOS 5?

This above example will not work on earlier versions of iOS - the UIRefreshControl class does not exist, nor does the RefreshControl property on UITableViewController. To get around this problem, the following code does a system check and falls back to an old-fashioned navbarbutton in earlier versions of iOS:

if (UIDevice.CurrentDevice.CheckSystemVersion (6,0)) {
    // UIRefreshControl iOS6
    RefreshControl = new UIRefreshControl();
    RefreshControl.ValueChanged += (sender, e) => { Refresh(); };
} else {
    // old style refresh button
    NavigationItem.SetRightBarButtonItem (new UIBarButtonItem (UIBarButtonSystemItem.Refresh), false);
    NavigationItem.RightBarButtonItem.Clicked += (sender, e) => { Refresh(); };
}

The Refresh method should contain the code that actually gets new data and updates the UITableView. That method should contain a similar if (CheckSystemVersion(6,0)) clause that wraps the call to the RefreshControl.EndRefreshing method on the main thread. Users on older operating systems will see this:

Wednesday, 19 September 2012

iOS 6 released, supported by Xamarin

It would be hard to miss the news that Apple is launching their new iPhone 5 this week, and has also released the final version of iOS 6. What's also great is that Xamarin supports iOS 6 too, on release day! There's already plenty of documentation, using C# with StoreKit, PassKit, EventKit, UIKit changes and more.

Of course there are heaps of little additions as well as those big ones, including a raft of new Core Image Filters to play with. For those working on the next Instagram (isn't everyone ;-), here's a preview of a couple of them:


(Posterize, Bloom, Invert, Perspective and Vortex)

For more information, review the Introduction to CoreImage in iOS 5 and the additional sample code for iOS 6. You might also like Apple's CoreImage Filter Reference.

Thursday, 13 September 2012

Microsoft's Azure Mobile Services... and WP7... and Mac

So far, Azure Mobile Services have been added to MonoTouch and Mono for Android (as well as Microsoft's getting started sample for Windows 8).
To complete the 'set', I ported the MonoTouch code to MacOSX using the free, open-source MonoMac AND used @kenegozi's 'unofficial' client to munge Azure Mobile Services into our existing Tasky sample on WP7.

These aren't production-quality implementations, mind you, just a couple of quick hacks to illustrate the beauty and simplicity of having C# and the .NET framework available across all these platforms. Oh, and also show the beauty of Azure Mobile Services :-)
You can grab the code for all of these from TaskCloud/Azure on github. You'll need to sign up for the Azure trial and follow the instructions to set up the Todo list tutorial.
Screenshots
Here's how the WP7 and MonoMac versions look:

Saturday, 1 September 2012

Microsoft's Azure Mobile Services... and Mono-for-Android

Yesterday's post introduced a quick implementation of Microsoft's Azure Mobile Services using MonoTouch to build an iOS app.
The WebClient and Json handling was easily refactored into a single class - AzureWebService - which was then added to the existing Android version of the Tasky sample... and now we have the same Azure Mobile Service being access by three platform clients: Windows 8, iOS and Android all with C# (and the iOS and Android apps sharing the service client code).

Additional features have also been added to AzureWebService to allow deletion of tasks. The Android app source is on github and it looks like this (delete has been added to the iOS app too):

Here is a discussion of how the API was reverse-engineered with Fiddler. The REST endpoints that TaskyAzure accesses are:

GET /tables/TodoItem

GET /tables/TodoItem/?$filter=(id%20eq%20{0})

PATCH /tables/TodoItem/{id}
{"id":1,"text":"updated task text","complete":false}

POST /tables/TodoItem
{"text":"new task text","complete":false}

DELETE /tables/TodoItem/{id}

Finally, only a few small updates were required in the Windows 8 example prevent the completed tasks from disappearing and instead make use of the checkbox in a more natural way:

Now all three apps are reading and writing to the same Azure data store! Can't wait for the official cross-platform APIs :-)

Friday, 31 August 2012

Microsoft's Azure Mobile Services... and MonoTouch

Microsoft only recently announced a cool new addition to the Azure product offering: Mobile Services. They have done a great job at providing a getting started tutorial that gives you a working Windows 8 app in about 5 minutes (seriously, it's fast and easy).

Azure Mobile Services consist of an underlying REST API, so it didn't take long for someone (Chris Risner :-) to put a simple iOS client together. That was all the inspiration required to get it working with MonoTouch.

Actually there is already a MonoTouch todo-list example called Tasky and it has previously been adapted to use Apple's iCloud storage.

The finished code for TaskyAzure borrows heavily from the existing Tasky samples (eg. it uses MonoTouch.Dialog), and really only borrows the REST API urls and Json from Chris' post. I might be biased, but the C# code looks a lot simpler to me :-)
Visit github for the TaskyAzure code. The app looks like this:

And just to prove that the Windows 8 app and the MonoTouch app are both writing to the same Azure database, here is a screenshot of the Azure Management Portal showing the data storage:
Azure Mobile Services looks pretty interesting - look forward to seeing the official cross-platform APIs :-)

UPDATE: to try the code follow the Microsoft's instructions, including creating a free trial account. Once your Azure Mobile Service has been created, configure the app by updating the constants in the AzureWebService.cs class:

static string subdomain = "xxxxxx"; // your azure subdomain
static string MobileServiceAppId = "xxxxxx"; // your application key

Thursday, 23 August 2012

In-app purchase vulnerability & MonoTouch

Earlier this year (around July) Apple announced that a vulnerability had been discovered in the in-app purchasing mechanism, which they discuss here. They provide some Objective-C code which:

  • Checks the information returned matches the information in the SKPayment
  • Checks that new transactions have a unique transaction ID
  • Verifies the SSL certificate
  • Verifies the receipt's signature

I've started a port of that code to MonoTouch, so far it only performs the first two mitigation steps. The VerificationController c# class is a gist.

Adding this code to a simple in-app purchase implementation would turn something like this:

into something like this:

where there is now an additional web request round-trip in your purchase code, plus a pile of comparisons to see whether the the StoreKit receipt matches the one you requested from iTunes directly. It also stores a list of every transaction ID in NSUserDefaults that is used to identify duplicates (which is an indication that the responses are being faked).

WARNING: the c# port currently only performs rudimentary checks comparing the receipt returned by StoreKit to one you've attempted to independently verify with iTunes. Without the SSL certificate and signature checks your code will still be vulnerable to sophisticated hacks on the DNS config to re-route requests and fake the responses. Please consider this a starting point for improving the security of your in-app purchase code.

NOTE: Apple says this vulnerability will be addressed in a future version of the operating system!

Friday, 17 August 2012

Image Metadata with MonoTouch

Developers frequently want to know how to extract metadata from an image file on iOS using MonoTouch. One alternative is to use MonoTouch.ImageIO.CGImageSource to query the image (without even having to load it into memory).

Here is an example on gist that shows how to use the CGImageSource class, and a screenshot of how it looks (you'll have to add your own image to the project):

The key lines of code are:

var imageFilename = "img.jpg";
var url = new NSUrl(imageFilename, false);
CGImageSource myImageSource;
myImageSource = CGImageSource.FromUrl (url, null);
var ns = new NSDictionary();
var imageProperties = myImageSource.CopyProperties(ns, 0);
// Output ALL teh things
//Console.WriteLine(imageProperties.DescriptionInStringsFileFormat);

// Basic Properties
var width = imageProperties[CGImageProperties.PixelWidth];
var height = imageProperties[CGImageProperties.PixelHeight];
var orientation = imageProperties[CGImageProperties.Orientation];
var dimensions = String.Format ("Dimensions: {0}x{1} (orientation {2})", width, height, orientation);
Console.WriteLine(dimensions); 

// TIFF Properties
var tiff = imageProperties.ObjectForKey(CGImageProperties.TIFFDictionary) as NSDictionary;
var make = tiff[CGImageProperties.TIFFMake];
var model = tiff[CGImageProperties.TIFFModel];
var dt = tiff[CGImageProperties.TIFFDateTime];
var tprops = String.Format ("TIFF: {0} {1} {2}", make, model, dt);
Console.WriteLine(tprops); 

// GPS Properties
var gps = imageProperties.ObjectForKey(CGImageProperties.GPSDictionary) as NSDictionary;
var lat = gps[CGImageProperties.GPSLatitude];
var latref = gps[CGImageProperties.GPSLatitudeRef];
var lon = gps[CGImageProperties.GPSLongitude];
var lonref = gps[CGImageProperties.GPSLongitudeRef];
var loc = String.Format ("GPS: {0} {1}, {2} {3}", lat, latref, lon, lonref);
Console.WriteLine(loc); 

// EXIF Properties
var exif = imageProperties.ObjectForKey(CGImageProperties.ExifDictionary) as NSDictionary;
var fn = exif[CGImageProperties.ExifFNumber];
var focal = exif[CGImageProperties.ExifFocalLength];
var eprops = String.Format ("EXIF: Fstop {0} FocalLength {1}", fn, focal);
Console.WriteLine(eprops); 
Xamarin already has a recipe explaining how to save a photo with metadata.

Sunday, 1 April 2012

CoreImage with MonoTouch (example)

In response to a question on the mailing list over the weekend I put together a quick example of using CoreImage in MonoTouch to adjust the Contrast, Saturation and Brightness of an image. It looks like this:
CoreImage with MonoTouch
The code is available in a gist; to use simply create a new MonoTouch Empty iPhone Project and paste in the code/create the files.
It initially uses a supplied image but you can take a photo with the camera and manipulate that instead. NOTE that when you take a camera image, a 'display copy' is made (scaled down to screen resolution) and the Contrast/Saturation/Brightness changes you make are applied to the scaled-down copy to ensure the UI is responsive and avoid memory issues. If you choose to save the image, the C/S/B values are re-applied to the original image before being saved, so you get an 'original resolution' verison saved to the Camera Roll.

There is also a CoreImage project on Xamarin's github which includes examples of many more CIFilters (see also Apple's docs). Plus there's a Sepia-tone example in the MonoTouch iOS5 doc.

FYI using CIFilters with MonoTouch is very simple as this method shows:
// the CoreImage filter  
CIColorControls colorCtrls;
// apply to an image
UIImage AdjustImage (UIImage image) {
   if (colorCtrls == null)
      colorCtrls = new CIColorControls () {
         Image = CIImage.FromCGImage (image.CGImage),
         Brightness = sliderB.Value, 
         Saturation = sliderS.Value, 
         Contrast = sliderC.Value
      };
   else {
      colorCtrls.Brightness = sliderB.Value; 
      colorCtrls.Saturation = sliderS.Value; 
      colorCtrls.Contrast = sliderC.Value;
      colorCtrls.Image = CIImage.FromCGImage(image.CGImage);
   }
   var output = colorCtrls.OutputImage;
   var context = CIContext.FromOptions (null);
   var result = context.CreateCGImage (output, output.Extent);
   colorCtrls = null;
   return UIImage.FromImage(result);
}

Sunday, 4 March 2012

iCloud UIDocument sample: taskcloud

One of iOS5's biggest new features was iCloud storage - the ability for apps to store data (files) "in the cloud" and access them from multiple devices, with OS-supported server-storage/upload, synchronization and backup.
Although it is possible to access "iCloud" functionality directly from within your code, Apple recommends using the new UIDocument class which has a lot of 'built-in' functionality to help manage iCloud documents. At its most basic, you only need to subclass UIDocument and override two methods (LoadFromContents & ContentsForType) to get it working.

The TaskCloud sample creates a TaskDocument subclass and contains some additional code to retrieve a document list from iCloud. The example is a little contrived - using a separate 'file' for each task might not be the best way to model a to-do list application - but you get the idea: individual tasks are created as files and iCloud synchronizes them across all your devices!
The code is still "under construction" so please forgive any dodgy practices. It also doesn't address the full iCloud API, such as conflict resolution or moving files to/from 'local' storage.

You can download the (MonoTouch) code from Github.

As a reminder, here is the guide for configuring your MonoTouch project for iCloud.



(see also, the iCloud Key-Value storage example)

Wednesday, 29 February 2012

iCloud Key-Value example: chat2self

Apple introduced a new API in iOS5 - iCloud Key-Value Data Storage - which lets your applications share a collection of key-value data between devices (with the same App Store login). It's fairly restricted (limited number of keys, limited data size, and no guaranteed time to sync), but it's also very easy to use.

Because the storage is only shared with the same user, it's pretty useless for a chat program. On the other hand, I was keen to play with Miguel's latest BubbleCell example. The result: a simple chat program that only sends messages between your iCloud-registered devices. Each device uses a single 'key' to save the last message you wrote on that device, and iCloud takes care of sync'ing that out to your other devices. When they receive the sync'd data, a notification kicks in and it appears in the conversation! It's definitely half-duplex...


Grab the (MonoTouch) code from Github. Remember: you'd never actually build a chat-service with iOS5 iCloud Key-Value Data Storage, this is just for fun :-)

UPDATE: some handy tips for setting up iCloud for MonoTouch development.



Monday, 18 July 2011

Xamarin welcomes MonoTouch and MonoDroid "home"

Great news! Xamarin has acquired a "broad, perpetual license" to the MonoTouch and Mono-for-Android work that was done while the dev team was part of Novell (prior to the Attachmate buyout kerfuffle). There's a press release on the Novell website and Miguel posted on his blog too. Congratulations to the Xamarin team!

Check out the product details at:
Start with the iOS Roadmap to find out what's coming up next.

Monospace is going to be great! Have you downloaded the app yet :-) ?

Wednesday, 13 July 2011

"M"osetta Stone II: ViewController → Activity

After my recent posts I received a question asking for tips on porting a MonoTouch app to MonoDroid. I'm going to take a crack at that over a couple of days - with the warning that you probably shouldn't rush out and buy either tool but wait for Xamarin's future Mono-on-iOS and Mono-on-Android products.

The purpose of the original "M"osetta Stone post was to give cross-platform developers a 'head start' with some high-level concepts. This post will look a little closer at a screen from the Monospace11 app: the Speakers list.


This may be a massive oversimplification, but...
if you have
___ in iOS
then you want
___ in Android
to
UIViewControllerActivitysubclass to present a screen/form/page to the user
ViewDidLoad()OnCreate()setup the UI
Add() or AddSubview()SetContentView()use in ViewDidLoad/OnCreate to 'attach' UI to display
ViewWillAppear()OnResume()load/re-load data that might change and bind to UI
UITableViewListViewvisual control that presents a scrolling list
UITableViewSourceAdaptersubclass to broker the display of a data collection to the UI
GetCell()GetView()to build the layout(UI) for each cell/row, including re-using cells/views for performance
RowSelected()ItemClick EventHandlerperform an action when a row is touched
RowsInSectionCounttell the table/list how many rows to cater for

Here's how it looks in a Visual Studio Class Diagram*
* I've greyed out some of the methods not relevant to the discussion - the iOS implementation of the alphabetic index down the right edge doesn't have an Android equivalent, for example

Notes:
  • UITableViewSource has been implemented as an nested class to resemble the iOS pattern of implementing the equivalent Obj-C protocols on the ViewController - this pattern makes no sense in Android so the classes are separate.
  • The MonoTouch example code builds the UI in C# (eg. tableView=new UITableView();AddSubview (tableView);) whereas MonoDroid loads layout XML files SetContentView(Resource.Layout.Speakers);. This can happen in both ViewDidLoad/OnCreate and GetCell/GetView where UI controls must be created and presented to the user.
  • The 'touch event handler' is in a different class: in MonoTouch the TableViewSource handles a touch for a specific row (NSIndexPath); MonoDroid implements the ItemClick EventHandler<ItemEventArgs> on the ListView for a given GetRow(e.Position).
  • Both examples use the constructor (TableViewSource/SpeakersAdapter) of the 'broker' class to pass the actual business object collection for display. This pattern lets the data be filtered/sorted/whatever before being passed in for display.
  • Calling refreshSpeakers() from ViewDidLoad/OnResume is kinda redundant in this example since the list never changes - but in other spots (eg the Favorites screen) you would want to refresh the list each time because it may have changed.

The Code
You can have a look at the MonoTouch code SpeakersViewController.cs and the MonoDroid SpeakersActivity.cs, SpeakersAdapter.cs to see the actual implementation. For MonoDroid you'll also need to check out the layout XML files Speakers.axml and SpeakersItem.axml.

One more thing...
One final piece which takes some getting used to... in MonoTouch this screen is part of a UINavigationController stack and your RowSelected creates a new ViewController object (passing whatever parameters you need) and calls NavigationController.PushViewController(). The ViewController instances in the navigation stack are 'stateful' and it is really easy to pass business objects around as parameters.
In MonoDroid, the ever-present 'back-stack' does not require a specific 'navigation controller' BUT at it's simplest the mechanism is much more primative and involves passing simple type parameters (eg. strings) like this
var intent = new Intent();
intent.SetClass(this, typeof(SpeakerActivity));
intent.PutExtra("Name", speaker.Name);
StartActivity(intent);

There are more sophisticated approaches but it is probably best to keep your parameter-passing to a minimum - this way the Android hardware 'Back' button "just works".

HTH Slava ;-)

Monday, 11 July 2011

MonoDroid v MonoTouch : a comparison

The past few days I've posted MonoDroid and MonoTouch apps for Monospace - and while they aren't perfect examples of the sort of code-sharing and efficiency that's possible with Mono I thought it would be interesting to compare them as the functionality they offer is very similar.

First, these are the high-level code metrics (as calculated by Visual Studio):
Unfortunately I didn't align the namespaces very well. Here's the explanation:

Total lines of code (TLOC)
Mono-for-Android: 802 lines
MonoTouch: 1,420 lines (2,033 - 613 in SQLite)
At first glance, the MonoDroid app 'wins' with just half the code of the MonoTouch version. I've ignored the SQLite library and the MonoTouch.Dialog framework as they aren't "user code", and any non-.cs files (eg XML markup).

Common code
Although difficult to 'see' because I've rushed these codebases into the public domain, there is a bit of 'code re-use' in these apps (ie. it was only written once, and the c# shared across both platforms using the power of Mono :)
ConfXml == MIX10Xml == approx 200 lines of business objects (DTOs mainly) that match the serialized conf.xml format that is the shared data structure for both platforms.
The ConceptDevelopment.Kelvin code is also shared (different sizes in each aren't relevant for now).

Removing the common code from the comparison results in these totals:
Mono-for-Android: 575 lines (802-199-28)
MonoTouch: 1,145 lines (1,420-178-97)

"Re-used" code
Mono-for-Android's Main.cs::DeserializeConferenceFile, LoadWhatsOn and MonoTouch's AppDelegate.cs::FinishedLaunching both contain "very similar" code in the form of the conf.xml deserializer and parser. In MonoTouch it's 70 lines and in MonoDroid it's 307 lines. The MonoTouch version is heavily assisted by the Linq/MonoTouch.Dialog code in HomeController (another 150 lines or so) which explains part of the difference... but what is shared is the deserialization logic and a number of Linq statements that help parse it for display. These would be harded to shift into a common library due to the dependency on MonoTouch.Dialog - but there was definitely an efficiency gain by having the code already written and tested on one platform before porting to the other. I'll adjust both by the same 'average' LOC count to try and reflect the 'copy/paste but modify' efficiency gain.

Mono-for-Android: 375 lines (575-200)
MonoTouch: 945 lines (1,145-200)

Feature parity
Adjust the MonoTouch solution to allow for the fact that it implements the Map feature that is not available on MonoDroid - 118 lines of code across a few classes.
MonoTouch: 827 lines (945-118)

What's left?
Once we've removed the libraries, the shared data structure, common code and allowed for some "copy/paste re-use", what's left to differentiate the two codebases? Basically just the UI and the code that binds our DTOs to it.
Mono-for-AndroidMonoTouch (iOS)
Code375 lines827 lines
'markup'14 AXML1 XIB
Views7 Activities9 ViewControllers
DataSources6 Adapters5 TableViewSource
Some notes on the difference:
  • There are 350 lines of AXML to define the layouts used in MonoDroid - the equivalent task in MonoTouch is done mostly in C#, significantly contributing to the LOC difference. I could have implemented a lot of that MonoTouch layout in XIBs using InterfaceBuilder - I just don't like doing it that way.
  • The UITabBarController takes more code to setup than
    OnCreateOptionsMenu.
  • The iOS SQLite implementation of saving Favorites is more verbose than the XML-serialized-file solution used on Android.
  • The MonoTouch source is almost 2 years old, and in some places isn't as succinct as it could be.

Conclusion
So is MonoTouch instrinsically more verbose than MonoDroid? I don't think so - it depends greatly on your preference for constructing your Views (XIBs or in-code). The more important question: does building with Mono* make it easier to port your app to other mobile platforms... and the answer is YES! In future this code might get tidied up into a good example of a cross-platform app... in that case I'll re-examine the stats to make an even better case.

Look at it this way: the iOS app took 1,400 lines of code (it was written first). For an additional 375 LOC (plus some layout XML) we got an Android port - almost for free!

Thankfully it sounds like Xamarin Studio is coming along nicely.

Saturday, 9 July 2011

MonoTouch for Monospace II

Further to the MonoDroid version, I've just submitted an iOS version of the Monospace 2011 conference app to Apple (fingers crossed it gets approved, and in time for the conference!).

Here's how it looks:

Even if it doesn't get approved in time, the code is open-source and can be found at github.com/conceptdev/Monospace11. It is based on the original Monospace09, PDC09 and MIX10 apps. A couple of guys helped out with the MIX10 version: @migueldeicaza, @kangamono and @chrisntr. I know Miguel in particular was keen for this code to be open-sourced... I think (?) it was one of the first outings of his awesome MonoTouch.Dialog library. I'd like to thank them again for their help (and to note that any remaining bugs or problems are mine). Also note: there is some old code in there (like, almost 2 years)... it scares me a little to put it up on Github, so please, be gentle.

I'll update with an AppStore link if/when Apple is done; but for now just enjoy the code :)

See you at Monospace!

Friday, 27 May 2011

Mobile UI Design ramblings...

Mobile UI design has come up a couple of times the past few days (as has Xamarin),
  • I'm looking to port an existing iOS app to Android - how 'same' should it look?
  • Nielsen Norman Group released their latest Useability of iPad Apps and Websites report
  • Ongoing discussion with @russaus
...so seemed like a good time to make some notes (and for UI, read UX and IA as well :)

Porting apps...
Porting apps from one platform to another (iPhone to Android, iPad to Android, or to Windows Phone, or from 'web', etc) always brings with it a challenge to make each version feel 'native' and embrace the platform's UI idioms & metaphors (while simultaneously re-using as much code as possible and keeping your application consistent across each). This can be seen in previous posts on the MIX11 app and the Restaurant Guide sample being ported to iPhone, Android and Windows Phone 7. Should the new Android app be a 'UI clone' of the iOS version? Should it be redesigned from scratch, removing any traces of iOS-ness? The answer is probably somewhere in between, being guided by your usability and branding goals, and by feedback from your users.
UPDATE: some thoughts on Why Are Android Apps Ugly? :-)

"Usability of iPad Apps and Websites": 2 reports
Coincidentally, while planning the UI for the Android app, Nielson Norman Group released an updated Usability Report for iPad Apps and Websites. The new edition (and the previous) are great reads (free to download) - some points will seem obvious, some will trigger "a-ha" moments and other's you'll disagree with; but overall you'll probably find it worthwhile to download them both.

References...
There are a couple of great websites worth looking at when you are doing UI design
  • mobile-patterns.com is a cool collection of screenshots from iPhone apps grouped into 'UX categories' like User Profiles and Lists. My favorite is Empty Data Sets - so often overlooked! (by @mari18)
  • ui-patterns.com is a more general collection (ie. not mobile) with categories like Getting Input and Navigation. It is a LOT deeper in terms of content (articles/discussion as well as screenshots) and likely to be thought-provoking no matter what platform you're working on. (follow @uipatternscom
  • UPDATE: Windows Phone 7 for Designers — Cheat Sheet kinda similar to the mobile-patterns site above but for Windows Phone. Poster-layout for easy printing/reference (by @teppo).


...and what about that whole MonoTouch/MonoDroid 'thing'?
Novell (Attachmate) says (my underline)
Focusing on what matters most to customers is the key to our innovation strategy and will drive the growth of our business. This has meant reductions in certain areas, such as Mono. However, Mono remains part of the SUSE business and should customer demand for Mono products accelerate, our development efforts will rapidly respond. Regardless, we will continue to provide maintenance and support for all Mono products – MonoTouch, Mono for Android, Mono Tools for Visual Studio and SUSE Linux Enterprise Mono Extension.
But it sounds disingenuous considering they have already sacked the entire team... and WTF does "should...demand...accelerate" mean? How is demand going to grow when they've killed any chance of enhancing the product and do not market it?? If they were truly "Focusing on what matters most to customers" they wouldn't have sacked the engineers in the first place, or else should have released/sold/transferred the Touch/Droid IP to Xamarin where it has some hope of a future (IMHO, anyway). </2centsworth>

Also, in related news, @migueldeicaza announced that Nat Friedman has joined Xamarin as CEO. Nat previously worked with Miguel as a co-founder of Ximian.

p.s. I'm *guessing* that we will be saying goodbye to the MonoTouch and Mono for Android product names since Novell probably owns them... wondering what I should use for Twitter hashtags now to replace #monotouch and #monodroid? Something with an 'X'? :)

Tuesday, 17 May 2011

MonoTouch/MonoDroid and Xamarin - what now?

If you are in the mono community then you'd have to be living under a rock not to have read that Novell was purchased by Attachmate then (first) heard the rumors that Attachmate Lets US Mono Developers Go and (second) seen Miguel's confirmation/announcement of the creation of Xamarin.

What I think this means is:
  • Mono should be fine. It has always been open-source (see github.com/mono) and receives contributions from a variety or people regardless of who they work for.
  • The MonoTouch and Mono for Android (aka MonoDroid) products published by Novell will effectively stop being supported "as of now". This is based on the fact that none of the devs work there any more.
  • Attachmate hasn't announced any plans for those products - even whether they'll continue to be available for sale (along with the associated activation servers). It's impossible to predict what will happen here... various people are trying to get answers from Novell/Attachmate. Personally, even if Attachmate attempted to continue selling/supporting the products I would choose not to be their customer as soon as alternatives are available.
  • Miguel and the team who built MonoTouch and MonoDroid have publicly announced they're working on comparable/compatible products to be sold by Xamarin (their new company). These new products are 3-4 months away, betas first prior to a real release. They've done it before, they can do it again!
Lots of people (myself included) have invested plenty of time and money purchasing, learning and using MonoTouch and MonoDroid. I even helped write a MonoTouch book (and some guys have been busy with a MonoDroid one too). We are all collectively upset, disappointed and angry (imagine how the devs themselves feel).

All of this uncertainty has provoked a number of reactions, among them suggestions that all the work done on MonoTouch/MonoDroid projects to-date has been wasted or that people should start learning the native SDKs for iOS and Android instead of committing to the Mono alternatives.


Learning the native SDKs has always been an option for anyone interested in mobile dev, but who wants to go to all that effort!? The value proposition for Mono* remains: .NET developers can leverage their existing language and framework knowledge AND code can be written once and re-used across three platforms (iOS, Android and Windows Phone). Those advantages continue to be true - the two products are definitely useable right now (MonoTouch obviously more mature than MonoDroid) - and if you care to take Miguel at his word they have a 'compatible' future. So what to do in the next 3 or 4 months...

I already have a MonoTouch/MonoDroid app written and published (or almost published)
Keep going! If everything is working for you right now, why change? In future you "might" need to port your work to native IF Xamarin's products are late/don't work. But if you start porting now and spend three months doing the conversion and Xamarin succeeds then you'll have wasted a lot of effort! What's more, your existing codebase will form an excellent 'regression test' for the Xamarin previews/betas... make sure you sign up at xamarin.com and participate! Your knowledge and experience with the existing products will be very helpful testing the new bits.

If you are really pessimistic you can still continue on this path - but maybe allocate some of your dev time learning the native SDKs and possibly prototype/porting some of your code. Don't do all of it - just get comfortable with the fact that it's possible while waiting to see how Xamarin develops.

I have purchased MonoTouch/MonoDroid and was planning to use them in future
Why not give them a try anyway? There are multiple benefits of using Mono*, including learning the native SDK APIs from the comfort of a language you know and also being productive more quickly. Think of it like prototyping - you get something working quickly and along the way learn a lot that can be re-used (you WILL learn the iOS/Android APIs).

If your app is single-platform I can imagine this decision might be a close call (and perhaps you should just learn Objective-C or Java) BUT if you are planning a cross-platform solution then you are still going to save time and effort with Mono* and code-sharing. One obvious risk would be the possibility of hitting something that isn't supported/doesn't work in Mono* yet - so do your research.

On the other hand, imagine spending the next few months learning BOTH Objective-C and Java, and producing two incompatible codebases for your app, only to discover that Xamarin rocks!

I'm a consultant and I've recommended MonoTouch/MonoDroid to clients
Ouch. This is bound to 'look bad' since the less your clients understand about the risk/reward of a tool like Mono*, the more they are going think you've stuffed up. In reality, though, the above points still apply - you can offer them the same bet: switch tools now and potentially waste some time or risk 'maybe' porting at a later time but take advantage of the benefits Mono* provides now... after all you recommended Mono* for a reason and many of those reasons are still valid.

I have done this myself - so I know how uncomfortable it feels.

I am interested in MonoTouch or MonoDroid but haven't purchased yet
This is a tough one. I'm not sure that the Novell Shopping Cart or the Activation Server are even working at the moment (activation behind an authenticating proxy is not supported at all). Even if they were, I'm not sure I'd want to give Attachmate my money. Maybe this will become clearer in the coming days/weeks.
You can definitely try out the 'free trial' (emulator only) editions but for a real project that you want to publish on AppStore/Marketplace soon I'm afraid you might need to consider learning the native SDKs or waiting a while... :-(

In conclusion...
I'll be the first to admit this is a very "glass half-full" point-of-view. Lots of bad s**t could happen: support issues with the current products that can't be resolved, legal issues with Attachmate, product delays from Xamarin, unexpected costs or incompatibilities for the new stuff, etc, etc, etc.

At the end of the day, you'll make a decision based on your risk-averse-ness (triple word score!) regardless of my rainbows and unicorns. Just keep in mind that the apparent 'end of life' of the current MonoTouch/MonoDroid products, while sad, is not (yet) the end of the world. In some ways, you can best support Xamarin by continuing to use the existing tools so that you've got something to migrate to their new stuff.

Make sure you've got some peanuts and a towel, and above all DON'T PANIC.