Returning with the iOS Keyboard

Almost all mobile apps have some sort of text entry. One of the main ways to do this is to simply add a text box. Adding a text box is both simple and easy to do, but we can take this a little further and improve the user experience.

Hiding the Keyboard

When the keyboard is shown by tapping a text box, the natural thing to do in order to hide it would be to tap outside the text box. However, this is not the case by default. But, this is easy to add by overriding the TouchesBegan method of the ViewController:

    public override void TouchesBegan (NSSet touches, UIEvent evt)
    {
        // hide the keyboard from all views
        View.EndEditing (true);

        base.TouchesBegan (touches, evt);
    }

Enabling/Disabling the Return Key

There is a very simple way to let the user know that some text is required: disable the return key if no text is provided. This can be done in both the code and in the designer. In the code we set the EnablesReturnKeyAutomatically property:

    textField.EnablesReturnKeyAutomatically = true;

There is a checkbox in the designer labeled “Auto-enable Return Key”.

It is important to note that this does not apply if the keyboard type is NumberPad as there is no return key for this keyboard type.

Changing the Keyboard Type

Another way to provide a basic restriction of the UI is to select a keyboard type. By selecting an appropriate keyboard type, the user can know what is expected to be entered as well as make the available characters easier to reach. If we only want numbers, we use the NumberPad as this removes the other keys. If we are providing an entry for an email address, we use the EmailAddress type which makes the @ and the . key more available:

    textField.KeyboardType = UIKeyboardType.NumberPad;

There is a dropdown in the designer labeled “Keyboard” which provides all the available options.

Keyboard Types on iOS

Changing the Return Key Type

Another nice user experience is to change the text for the “return” key, which provides additional hints as to what is going to happen with the input. There are several options that are available, such as Done, Search or Next:

    textField.ReturnKeyType = UIReturnKeyType.Done;

There is a dropdown in the designer labeled “Return Key” which provides all the available options.

Adding an Action to the Return Key

When the user presses the return key on the keyboard, we would expect something to happen, especially if it is a single line textbox. But, on iOS nothing happens, so we attach a delegate that can hide the keyboard and maybe do some more work. This is easy to add by assiging a delegate to the ShouldReturn property of the UITextFied:

    textField.ShouldReturn = delegate {
        // hide the keyboard
        textField.ResignFirstResponder ();

        // the "return" logic here

        return true;
    };

Adding “Return” to the Number Pad

As the NumberPad keyboard type does not have a return key, there is no default way to hide the keyboard, we have to manually add a handler to hide the keyboard when another view is tapped. Another way we can do this is to add a “Cancel” or a “Done” button accessory to the keyboard:

    // create the toolbar
    UIToolbar numberToolbar = new UIToolbar ();
    numberToolbar.BarStyle = UIBarStyle.Default;
    numberToolbar.Translucent = true;
    // set the items
    numberToolbar.Items = new [] { 
        // the cancel button
        new UIBarButtonItem (UIBarButtonSystemItem.Cancel, delegate {
            // hide the keyboard
            idEntryTextField.ResignFirstResponder ();
        }),
        // the space to separate the buttons
        new UIBarButtonItem (UIBarButtonSystemItem.FlexibleSpace, null),
        // the "continue" button
        new UIBarButtonItem ("Login"), UIBarButtonItemStyle.Done, delegate {
            // hide the keyboard
            idEntryTextField.ResignFirstResponder ();

            // the "return" logic here
        })
    };
    // fill the screen width
    numberToolbar.SizeToFit ();

    // set the accessory
    textField.InputAccessoryView = numberToolbar;

Xamarin Insights for Older Androids

Recently, Xamarin announced a real-time crash reporting and analytics solution for mobile apps, Xamarin Insights.

This is an awesome tool with many great features. They support all the major platforms, iOS Android Windows Phone, Windows RT and traditional desktop applications. Support for Xamarin.Mac is coming soon.

Some of the major features:

  • Report details about the device statistics such as operating system and screen resolution
  • Gather and report any uncaught native or managed exceptions
  • Report any caught exception, along with any additional data
  • Track both past and active sessions
  • Track any event that occurs in your application, including the time it takes to execute
  • Cross-platform across almost all devices, including support for PCL libraries

Old Androids

Recently they added support for Android versions below API level 14 (Android Version 4.0 – Ice Cream Sandwich). To use Xamarin Insights in an Android app below API level 14, such as API Level 8 (Android Version 2.3 – Gingerbread), there are a few things that need to happen:

  1. Set your ‘Compile using Android version’ or ‘Target framework’ value to be API level 14 or higher, such as API level 19
  2. Set the ‘Minimum Android to target’ or ‘Minimum Android version’ to be the value you are wanting to support, such as API level 8.

This will result in your app building against the higher API level, but can run on earlier devices.

However, even after all this, there is still a limitation, namely the inability to record sessions. This may not be a deal breaker for you, but for some, this is. The reason for this is that Xamarin Insights is using the IActivityLifecycleCallbacks interface. This is a relatively new addition to the Android API and is very useful in that it allows you to hook into the Activity lifecycle without having to use the Activity itself. As this interface is not available for the older versions, they simple can’t record the Activity sessions.

The Code

I am here to give you that solution that you always wanted: Manually starting and stopping sessions from within the activity. To do this I have created a simple class InsightsCompat:

    public static class InsightsCompat
    {
        public static void Initialize(string apiKey)
        {
            Insights.Initialize(apiKey, Application.Context);
        }

        public static void StartSession()
        {
            EmitBackgroundChange(false);
        }

        public static void StopSession()
        {
            EmitBackgroundChange(true);
        }

        private static void EmitBackgroundChange(bool backgroundState)
        {
            try
            {
                var status = backgroundState ? "Background" : "Resumed";
                var table = new Dictionary<string, string> {{"Status", status}};
                Insights.Track("X-App-State", table);
            }
            catch (Exception ex)
            {
                Insights.Report(ex);
            }
        }
    }

The Usage

This simple class can do all the work that is needed, plus there is an additional method, Initialize, that allows you to start up Xamarin Insights without having to find the context:

    // from anywhere in your code
    InsightsCompat.Initialize("your API key");

To start and stop sessions, you can override the OnResume and OnPause methods:

    protected override void OnPause()
    {
        InsightsCompat.StopSession();
        base.OnPause();
    }

    protected override void OnResume()
    {
        base.OnResume();        
        InsightsCompat.StartSession();
    }

We only have to override these two methods as android will always call these methods, no matter where the Activity came from or where it is going.

There’s More

Even though Xamarin Insights has many features, it is still in preview and there can still be many more features. If you have any feature requests or ideas, be sure to drop a message on the Xamarin Insights User Voice.

There is a small docs page for Xamarin Insights here. So head over to the dashboard and get started creating and supporting awesome cross-platform apps now.

MVVMCross Startup Crashes

Have you every used MvvmCross in your app, only for it to crash on startup when launching without the debugger? Well it happened for me quite a few times, and its because I was having a brain fart…

After launching the app many times and trying to somehow gain knowledge magically due to repeating the same thing over and over, I decided to add some “logging”:

    // Code to execute if a navigation fails
    private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        MessageBox.Show(e.Exception.ToString()); // <- LOGGING!
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // A navigation has failed; break into the debugger
            System.Diagnostics.Debugger.Break();
        }
    }

    // Code to execute on Unhandled Exceptions
    private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
    {
        MessageBox.Show(e.ExceptionObject.ToString()); // <- LOGGING!
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // An unhandled exception has occurred; break into the debugger
            System.Diagnostics.Debugger.Break();
        }
    }

This returns a nice little error message:

System.NullReferenceException: Object reference not set to an instance of an object.
  at Cirrious.CrossCore.Mvx.Resolve[TService]()
  at MvvmCrossSample.WindowsPhone.App.<RootFrameOnNavigating>b__0()

So what does that mean? Well, over there I am trying to resolve the IMvxAppStart type:

RootFrame.Dispatcher.BeginInvoke(() => { 
    Mvx.Resolve<IMvxAppStart>().Start();
});

So for some reason, my Setup object wasn’t getting initialized… This is what I had:

    // Show graphics profiling information while debugging.
    if (System.Diagnostics.Debugger.IsAttached)
    {
        // ...

        Setup setup = new Setup(RootFrame);
        setup.Initialize();
    }

Hmm… Maybe the app should start up for the users without debuggers as well? All I needed to do was to move the startup object out of the scope of the if block:

    // Show graphics profiling information while debugging.
    if (System.Diagnostics.Debugger.IsAttached)
    {
        // ...
    }

    Setup setup = new Setup(RootFrame);
    setup.Initialize();

After that, the app worked fine.

In short, don’t just copy-and-paste when using templates, at least read the snippet you are pasting.

Running Mac OS X in Windows 8

Have you ever wanted or needed to run OS X on your Windows PC? I certainly did. As I am a developer of multiple platforms, Android, iOS and Windows, I would like to use one device to develop for all platforms, and of course using Visual Studio.

In order to install Mac OS X in VMWare on a PC, there are a few things that are needed:

  1. the OS X operating system (from an existing Mac)
  2. a Windows machine
  3. UniBeast
  4. VMWare Workstation
  5. Hackintosh VMWare Template for OS X

Now to get started, we have to get the OS X from the physical Mac. The first thing that we are going to do is prepare a bootable USB drive that we will use to install the OS on the VM.
In order to do this, there are a few steps (in order to do anything, we need to make sure that we have downloaded OS Mavericks from the App Store):

  1. Insert a USB Drive of at least 8GB
  2. Use Disk Utility:
    1. Choose USB Drive
    2. Choose Partition (Partition Layout: 1 partition)
    3. Under options choose Master Boot Record
    4. Choose Format (Mac OS Extended (Journaled))
    5. Click Apply
  3. Use UniBeast
    1. Download UniBeast
    2. Run Unibeast
    3. Choose USB Drive
    4. Select Mavericks 10.9
    5. Continue – This takes a while (not less than a minute)

Once we have done this, we should have a bootable USB drive containing Mavericks. Now we need to prepare our Windows machine. As there can only be one instance of hypervisor running, we may have to disable Hyper-V. If you don’t have Hyper-V installed, you can skip this step.

In order to disable Hyper-V, we are going to create a boot profile that will start up our PC without Hyper-V.
The first thing we need to do is to create a copy of our current boot profile. From the command line, execute this command:

    bcdedit /copy {current} /d "Disable Hyper-V"

This command creates a copy of our current profile {current} and creates a new profile with the name Disable Hyper-V. This name could be anything we like. This command will return a GUID that we are going to use in the next step to disable Hyper-V:

    bcdedit /set {INSERT-GUID-HERE} hypervisorlaunchtype off

This command disables Hyper-V for the profile with the GUID {INSERT-GUID-HERE} from the previous command.

If we restart our computer now, we should be presented with two options: “Windows 8.1” and “Disable Hyper-V”. Everytime we wish to use VMWare, we need to start with the “Disable Hyper-V” profile. This profile is exactly the same as the “normal” profile, just without Hyper-V, so you can use this profile for typical development as well.

The next thing to do is install VMWare:

  1. Install VMWare Workstation 10
    (the free VMWare Player will work as well to playback VMs)
  2. Install Hackintosh Template for OS X
  3. Create a Virtual Machine with Workstation 10 Compatibility hardware
  4. Install Operating System Later
  5. Choose OSX 10.9
  6. Add desired Hardware with at least 40 GB disk space allocated to the Virtual Hard Disk.
  7. Run NAT preferably
  8. Insert USB Boot Drive Created on Mac into PC
  9. Boot Virtual Machine
  10. Under VM > Removable Disks > Connect the USB Drive
    (this will remove it from visibility to Windows Host)
  11. Reset the VM
  12. OS X should install

That’s it! You should now have Mac OS X running on your PC!

Binding Flurry Analytics with Xamarin.Android

This week, I needed to use Flurry Analytics in my Xamarin.iOS and my Xamarin.Android apps, but there was no .NET SDK for these platforms. Flurry did provide a SDK for each platform, but it was the native libraries, which cannot be used directly in .NET. Given this, I decided to bind those native libraries using Xamarin.iOS and Xamarin.Android.

I have split this project up into four parts:

  1. Introduction and Pre-requisites
  2. Xamarin.iOS binding
  3. Xamarin.Android binding
  4. Flurry.Analytics in the wild

After binding the iOS SDK for Flurry Analytics, we are going to move onto the Android release. This task needs only one thing from the downloaded SDK:

  • [Android-sdk-path]/Android 4.1.0/FlurryAnalytics/FlurryAnalytics-4.1.0.jar

Of course, the version numbers may change for later releases. The java archive file (.jar) is going to be used to generate the .NET interfaces and enums, and then be embedded in the resulting assembly.

Just before we do the real binding, we should just create our C# solution for the Xamarin.Android binding. Just create a new project/solution and select the Android “Bindings Library” template. For my project name I used Flurry.Analytics.Android, but you could use anything.

The default project has a few files and directories in it, we will have a look at each one in depth as we go through the binding steps:

  • /Additions/ (this allows you to add arbitrary C# to the generated classes
    before they are compiled)
  • /Properties/AssemblyInfo.cs (the usual assembly information attributes)
  • /Jars/ (this directory is for Android .jars)
  • /Transforms/EnumFields.xml (this allows you to map Java int constants to C# enums)
  • /Transforms/EnumMethods.xml (this allows changes to method parameters and return types from Java int constants to C# enums)
  • /Transforms/Metadata.xml (this allows changes to be made to the final API)

Creating the Initial Binding

This step will involve just adding the jar to the project, and letting the compiler do it’s thing, but we will almost always have to go in and tweak a few things in the Metadata.xml.

So, first things first, add the jar file to the project and compile. The build will probably fail with error messages containing single character methods and types. This is because the actual jar file has been obfuscated. However this can easily be fixed.

The way the generation works is that there is a two step process, there is a tool that generates a bunch of xml files from the jar file. These xml files are then used to generate C# code. The Metadata.xml sits in between the two steps and can be used to transform the generated xml before the C# generation.

Tweaking the Generated Binding (Manifest.xml)

As we can see that the build fails on obfuscated types, we can remove these. The removal is safe as we are only preventing the .NET binding from being created, not actually removing the underlying Java members. And, as these items have been obfuscated, we can safely assume that we aren’t supposed to be accessing them anyway.

But, instead of removing each member or type that appears, we can use a great tool that will decompile the jar file and show us exactly what types are internal and what types we should be binding. I use JD-GUI, which is a free Java decompiler. They also have a nice online version, JD-Online. What we can do is to just upload the jar file here and see what’s inside:

  • com.flurry.android.impl.analytics.*
  • com.flurry.android.*
  • com.flurry.sdk.*

As we can see, the impl and sdk branches contain internal and obfuscated types, so we can remove those:

<remove-node path="/api/package[starts-with(@name, 'com.flurry.sdk')]" />
<remove-node path="/api/package[starts-with(@name, 'com.flurry.android.impl')]" />

After this, the build should now succeed and we will have an assembly that we can use. However, there are still some types that we can remove to clean the API a bit: InstallReceiver and Constants. InstallReciever is not used by the consumer, so this is safe to remove, but Constants is still used. If we remove this, then the consumer will not have access to the values on the type. We can see that Constants just contains the values representing male, female and unknown.

To remove the InstallReciever, we can add this line to Metadata.xml:

<remove-node path="/api/package[@name='com.flurry.android']/class[@name='InstallReceiver']" />

For the Constants type, we will do something different.

Managing the Enumerations (Additions & EnumFields.xml)

As we clean up the API, we want to remove the Constants type and replace it with an enum. One way to do this is to use the EnumFields.xml:

<mapping clr-enum-type="Flurry.Analytics.Gender" jni-interface="com/flurry/android/Constants">
    <field clr-name="Male" jni-name="MALE" value="1" />
    <field clr-name="Female" jni-name="FEMALE" value="0" />
    <field clr-name="Unknown" jni-name="UNKNOWN" value="-1" />
</mapping>

This will generate a nice enum for us, but this does leave an unused interface IConstants. As this is a very small library, we can do this mapping slightly differently. First we remove the entire Constants type in the Metadata.xml:

<remove-node path="/api/package[@name='com.flurry.android']/interface[@name='Constants']" />

Then, we can create the enum in the /Additions/ directory. To do this, add a new file (for example called FlurryAgent.cs) under this directory and add the enum:

public enum Gender
{
    Male = 1,
    Female = 0,
    Unknown = -1
}

Now there is one last thing to do before the API definition is complete. There is a SetGender method on the type FlurryAgent, which takes the type sbyte. It is not intuitive to use the Gender enum here, so we can fix this in a two step process. First we will create an overload in the FlurryAgent.cs file that accepts a Gender enum member as an argument:

public partial class FlurryAgent
{
    public static void SetGender(Gender gender)
    {
        FlurryAgent.SetGender ((sbyte)gender);
    }
}

And, what we can do is also hide the original member as the new overload is good enough:

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='setGender']" name="visibility">internal</attr>

And with this, our binding is complete, although we can do a few nice changes to the namespace and parameter names.

Changing Parameter Names

Now that we have the binding complete, we can see that it is using the namespace Com.Flurry.Android, which is no .NET-like at all. We can change this to something better:

<attr path="/api/package[@name='com.flurry.android']" name="managedName">Flurry.Analytics</attr>

This maps the com.flurry.android package name to the neat Flurry.Analytics namespace. One last thing is to fix the parameter names. Sometimes you can use the JavaDocs, but in this case, I couldn’t get it to work. Doing it manually is not hard, but it is boring and time consuming, but here are a few.

This is the usual mapping:

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onStartSession']/parameter[@name='p0']" name="name">context</attr>
<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onStartSession']/parameter[@name='p1']" name="name">apiKey</attr>
<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onEndSession']/parameter[@name='p0']" name="name">context</attr>

If there are complicated parameter types (note the &lt;):

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='logEvent']/parameter[@name='p1' and @type='java.util.Map<java.lang.String, java.lang.String>']" name="name">parameters</attr>

If there are overloads with different parameter types:

<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onError']/parameter[@name='p2' and @type='java.lang.Throwable']" name="name">exception</attr>
<attr path="/api/package[@name='com.flurry.android']/class[@name='FlurryAgent']/method[@name='onError']/parameter[@name='p2' and @type='java.lang.String']" name="name">errorClass</attr>

After doing this for all the members, the binding is now complete.

Finishing Up

So far we have defined our API, added any additional logic or types, added the native library and added parameter names. This is all that is needed, so our library should build fine now and we should be able to use it in an Xamarin.Android app:

// the methods
FlurryAgent.StartSession(this, "PQSZJRK4B5BW8Q7YQQXF");

// the properties that we changed back into methods
string version = FlurryAgent.ReleaseVersion;

// the extra method that we added
FlurryAgent.SetGender (Gender.Male);

MonoGame Content without Visual Studio

MonoGame is free software used by game developers to create games for many different platforms. It is almost a Write Once, Play Anywhere!

Unfortunately, the content processing pipeline is not yet available for all platforms or even the later versions of Visual Studio. Here I will show you a way to build the content for any version of Windows, without Visual Studio.

Platforms

Currently supported platforms for MonoGame:

  • iOS (including Retina displays)
  • Android
  • Windows (OpenGL & DirectX)
  • Mac OS X
  • Linux
  • Windows Store Apps (for Windows 8 and Windows RT)
  • Windows Phone 8
  • PlayStation Mobile (currently 2D only)
  • OUYA, an Android-based gaming console

Currently Supported platforms for XNA:

  • Windows Phone 7
  • Xbox 360
  • Microsoft Windows

Support for Xbox One is currently under way with both Microsoft and the MonoGame teams. Microsoft is adding .NET support to the Xbox One and the MonoGame team is adding Xbox One support to MonoGame.

Content Processors

When creating games using MonoGame, there are 2 main parts to any game: the Content and the Code. The content is usually the textures, sounds and fonts in the game. The code is what you write, the logic.

At the current time MonoGame does not have its own content processors, so we will make use of the original XNA build tools. The MonoGame team is working on their tools, but it is not yet complete.

In order to process the content, we need two things: the processor tools and some sort of UI.

Installing the Content Pipeline

We will start off by setting up our content tools before we actually do anything. First we need the assemblies that come with XNA Game Studio. This is the toolset used for building the content that will appear in our game. The actual studio does not install on without Visual Studio 2010, so we have to cheat a bit.

First of all, we need to download XNA Game Studio 4.0 Refresh from Microsoft’s Download Center. Once this is complete, we will load the framework installers out of the studio setup file:

  1. Using 7-zip (or any other compression tool), open the newly downloaded XNAGS40_setup.exe.
  2. Inside the installer, there should be a redists.msi file, open it using “Open Inside” as we don’t want it to start installing.
  3. Extract the files named SharedFilesInstaller_File, XNAFXRedist40Setup_File and XNAPlatformToolsInstaller_File into a directory.
  4. Rename the three extracted files by adding a .msi extension in Windows Explorer, this “turns” them into installers.
  5. Install each of them one at a time.

Once this is done, we would have installed all the build tools required to package the content.

Installing the Interface

Next, we need to install the XNA Content Compiler. This allows the building of the content packages when not using Visual Studio 2010.

You can do this by downloading the XNA 4.0 Content Compiler source code from my fork. I have added some extra features that allow for more advanced content processing, such as, Compression and MipMap generation.

Once you have this, you should be able to open the solution in Visual Studio and build the application. Currently the compiler can only be used on Windows as the tooling is only available on Windows.

Xamarin Has Options

Have you ever wanted to try out creating a mobile app for either iOS or Android using Xamarin? You went to their website, clicked pricing and then reeled at the cost? You are new. You are unsure. You want a taste. You don’t want to spend all your money and then maybe be a little unhappy.

Well, don’t worry, there is an pricing option for you! There are a couple of good ones that can fit your needs as someone stepping into a whole new world of magic.

You can check out the pricing and comparison charts at the Xamarin Store.

The Free ($0/m or R0/m)

Xamarin provides a free, zero cost, no cash option. Starter Edition! You may think that this is too limited. Only small apps. No native library interaction.

You are right. But. How small is small? Also, what are you measuring? The limit is only the size of the compiled source code, not the whole app. Chances are you aren’t going to hit any limit in your first week. The small app limit is almost a myth!

No native library interaction? What if I want to use… Is it a big no? No! With Starter you can use third party libraries that are available in the Component Store or on NuGet. And again, the chances are you aren’t going to be using some obscure framework on the first go. Both iOS and Android are mature platforms with many features, so probably what you need is already there.

The Indie ($25/m or R260/m)

But… Let’s say you need to write some custom native bindings or you have this massive app… There is a version for you still. But, if this is the case, how about giving the Indie Edition version a shot?

You recall looking at the price for this one… $299, or if you are with me in South Africa, R3200 at the current exchange rate. Pricey! Very much so…

But, Xamarin marketing to the rescue! They sat down and had a chat… What can Xamarin do so that the company makes a profit, but make sure the developer also can get a profit? So they came up with a subscription plan. A pay-as-you-go, or pay-for-what-you-use.

This new model, just out this week, provides you with a monthly subscription that can be started and stopped at your hearts content.

Lets say for example you are a student… You are studying hard like all students and don’t have much free time. But, you want to write an app in the holidays. It is going to be a big app. Starter ain’t gonna cut it. I’ll just note here that Starter probably would be fine for a case like this, but just to continue… You want Indie for one, maybe two months at most. Are you going to spend thousands of Rands? No. So you sign up for the Subscription Indie package.

What this does for you is that you will pay a small amount, and then get that month of development time. So in the example of the student, you sign up in June, pay your fee and do some dev. Then in July, you pay the next bit, and do some more dev. Then you release your app and go back to the books. August comes, you get a bill from Xamarin, and you just ignore it! They will suspend your account, so no more dev, but your app is out there and will is good.

Then after your exams, near the year end, you decide to do an update. All you need to do is pay that month’s bill and all is working again. Writing code until the sun comes up again.

So how’s much does this cost? Is it going to break the bank? Nope, it works out well. Each month costs $25, or for those in South Africa, R260. This cost is for either Xamarin.iOS or Xamarin.Android platforms. And not only that, you get access to some Xamarin exclusives, such as the new Xamarin.Forms. You can also subscribe to both platforms and get a 10% discount!

The Student ($99/y or R1000/y)

And, after mentioning students, remember they do have a special Student Discount for you. All you have to do is send student@xamarin.com an email from your student email address and they will send you a discount code. For as little as $99, or R1000, you get access to the Business Edition of either Xamarin.iOS, Xamarin.Mac or Xamarin.Android. And remember the business edition has even more features. My personal favorite is Visual Studio support! This allows you to build not only Android apps in Visual Studio, but also iOS apps! With a drag-and-drop designer!

If you are part of an Open Source project you can also get a complimentary license! All you need to do is fill in the Open Source Contributor Form and someone will get back to you!

Be sure to check out the new pricing options as well as the student and open source discounts!

The Xamarin User Group (XUG)

If you haven’t had a chance to meet your neighborhood Xamarin developers in person yet, Xamarin User Groups provide a perfect venue for connecting with like-minded developers and local experts.

If you are in Cape Town, South Africa, be sure to pop in to our monthly Cape Town Xamarin User Group, I’ll be there!

And also download the iCalendar.

The University ($1995/y or R2100/y)

Have you ever wanted to be better, do better, know more, finish first? Well you can get there by learning from the Xamarin cross-platform expert lecturers at the Xamarin University.

After taking a few classes, you can become a Xamarin Certified Developer, which shows that you have demonstrated expertise in cross-platform mobile development in iOS, Android, and Windows using the Xamarin platform.

Why would you want to get this certification? Well…

  • It is a premiere badge of achievement in Enterprise Mobile Development and an outward illustration that you’ve met a high bar of demonstrated expertise as a Xamarin Developer.
  • You are eligible to be included in the Official Xamarin Certified Developer LinkedIn Group: a curated professional network that only includes currently certified developers that get special access to mobile development jobs and other benefits.
  • You can proudly display the Xamarin Certified Developer Badges on your website or resume.

Xamarin University allows you to study at your own pace and at your own times. All you do is take a yearly subscription for $1995, or for us South Africans, R21000. This is a high price as it stands, but it does give you a certification, live web lectures and one-on-one feedback and discussions. This is often things that other recorded-video courses can’t provide.

Be sure to check out Xamarin University or contact them for more information.

ADB DEVICES >> No Devices Found

When building apps for Android using obscure devices such as the one I was using, sometimes the ADB (Android Debug Bridge) cannot find the device. I spent a long time trying to find out why my device was not appearing in adb, as Windows picked it up in the Device Manager and in Windows Explorer.

Usually, just installing the “Google USB Driver” by using the Android SDK Manager, results in all you problems going away. But, with the more obscure devices, this sometimes does not fix the issue.

The first step is to ensure that the device is installed. This can be checked by using the Windows Device Manager. If the device is not installed, it will be under “Other Devices”, then you just need to install it manually. If you downloaded the drivers by using the Android SDK Manager, then you can find them in a subfolder of the SDK ([sdk]\extras\google\usb_driver\). There should be a file called android_winusb.inf. There is also another way to obtain these drivers without using the Android SDK Manager, and that is directly off their website (latest_usb_driver_windows.zip). You can then extract the files to a convenient location so that you can install the drivers using the Device Manager.

  1. To install the drivers, you can right click the “Unknown Device” under “Other Devices” (It may be a partial/vague bit of a device name – for example, mine is just “Full”), and click “Update Device Software…”. This will start the wizard.
  2. On the first page, you can click “Browse my computer for driver software” (we want to select our downloaded files manually).
  3. We then click the “Let me pick from a list of device drivers on my computer” button as we want to do the install manually as Windows will not detect the driver as they are generic.
  4. The first item in the list of hardware types will be “Show All Devices”, select that and press “Next”.
  5. On the next page, there will be a “Have Disk…” button. Press that and then we can browse to where we have either extracted or installed the drivers to (the file we must select is android_winusb.inf). Press “OK” and then you should be back to the page that contains the “Have Disk…” button.
  6. Above the button will be a list with 3 items, select the “Android ADB Interface” and press “Next”.
  7. Windows will show a warning dialog that says that the device driver is not recommended. We can safely press “Yes” as this is just because this is a generic driver.
  8. Windows will install the driver and when it is finished, we can close the window.

Our device (“Android ADB Interface”) should now be under the “Android Device” item. The device is just installed, and this may be all we need. You can run the ADB DEVICES command to see if the device is detected.

If the device is not detected, then we may have to manually specify the device as a valid Android device for ADB. In order to do this we need to find out our device Hardware ID.

  1. We can obtain the Hardware ID via the Device Manager. We can just right-click out newly installed “Android ADB Interface” item and press “Properties”.
  2. On the “Details” tab, select “Hardware IDs” from the dropdown. There may be one or more items here, but you can use the one that starts with “USB\VID_####” (the #### is the 4 character device Hardware ID). I have an item labeled “USB\VID_2207&PID_0010&REV_0222&MI_01”, thus my Hardware ID is “2207”.
  3. Now, the short way to add the device to ADB is to just add the device Hardware ID to the adb_usb.ini file (%USERPROFILE%.android\adb_usb.ini).
  4. If this file does not exist, you can safely create it.
  5. Open the file in Notepad and add a new line to the end of the file in the form “0x####” (again the #### is the Hardware ID). In the case of my device, I added a line “0x2207” to the bottom of the file.

You should be able to now restart ADB and the device should be listed. You can do a restart by running 2 commands ADB KILL-SERVER and then ADB START-SERVER.

As the Android SDK Manager may overwrite the files here, you changes may be lost later. The correct way to ensure the install the device for ADB is to create a new add-on. This is simply creating a new file in a new folder under the “add-ons” folder in the SDK ([sdk]\add-ons\).

  1. The first thing to do is create a new folder for you add-on. You can pick any folder name as long as it won’t conflict with any other add-ons. I picked “small-tablet” as I don’t think that is a add-on name that is used elsewhere.
  2. Inside that new folder, create a manifest.ini file.
    • name – the add-on name
    • api – the API level on the device – mine was 4.0, thus 14
    • usb-vendor – the hex Hardware ID – mine was 2207, thus it will be 0x2207
  3. The item should now appear in the Android SDK Manager under “Extras”.

The contents of the manifest.ini file should be something like this, with the most important items:

name=small-tablet
vendor=Who Knows
description=That cheap 7″ tablet
api=14
revision=1
usb-vendor=0x2207

And there we go, we now have a nameless device in our Android SDK Manager.

Binding Flurry Analytics with Xamarin

Over the last few days I have been creating a Xamarin.iOS and Xamarin.Android binding for Flurry Analytics SDKs. Flurry Analytics is a neat little library that allows for tracking of your app usage and various user stats.
And, because I really enjoyed my time doing this, I thought that I will share just a bit of the fun times and the not-so-fun times.

I have split this project up into four parts:

  1. Introduction and Pre-requisites
  2. Xamarin.iOS binding
  3. Xamarin.Android binding
  4. Flurry.Analytics in the wild

Pre-requisites

Before we start any coding, we need to get all our tools and files needed for the actual binding tasks.

I was using both Windows 8, with Visual Studio, and Mac OS X with Xamarin Studio. You can bind the Android library on either platform, but for iOS, it is easier to use the Mac. In this case, I will use the Mac for both iOS and Android.

Some of my very excellent sources for this process were the actual Xamarin documentation:

But, along with this info, there are just a few things that you may need. Firstly, it is good to update your Xamarin Studio to the latest stable release as this makes sure that all potential problems are minimized from the start.

Then, the next cool tool to get hold of is, Objective Sharpie, for binding iOS libraries. This tool is quite nifty for quickly generating the .NET interfaces from the Objective-C header files. It uses the header files not the actual compiled native library. The Xamarin docs on Objective Sharpie has a brief walkthrough on how to use the tool, so I will assume you know how to use it.

After we have all our tools ready to go, we need those SDKs from Flurry.

What I did was to create a free account by Flurry, and then created an Android and iOS Application using their dashboard. You have to have an application before they will let you download their SDKs. This step is pretty straight forward, so I won’t go into it here right now. Once you have created and downloaded the SDKs, you can extract them to a nice location for reference.

Now to get started with the real work…

But, as this is quite a long process, I will be splitting this article into this intro, the iOS binding and the Android binding. So, enjoy!

Binding Flurry Analytics with Xamarin.iOS

This week, I needed to use Flurry Analytics in my Xamarin.iOS and my Xamarin.Android apps, but there was no .NET SDK for these platforms. Flurry did provide a SDK for each platform, but it was the native libraries, which cannot be used directly in .NET. Given this, I decided to bind those native libraries using Xamarin.iOS and Xamarin.Android.

I have split this project up into four parts:

  1. Introduction and Pre-requisites
  2. Xamarin.iOS binding
  3. Xamarin.Android binding
  4. Flurry.Analytics in the wild

The first thing we are going to bind is the iOS SDK for Flurry Analytics. This task needs two things from the downloaded SDK:

  • [iOS-sdk-path]/Flurry-iOS-5.2.0/Flurry/Flurry.h
  • [OS-sdk-path]/Flurry-iOS-5.2.0/Flurry/libFlurry_5.2.0.a

Of course, the version numbers may change for later releases. The header file (.h) is going to be used to generate the .NET interfaces and enums. The library (.a) is going to be used in the project.

Just before we do the cool things, we should just create our C# solution for the Xamarin.iOS binding. Just create a new project/solution and select the “iOS Binding Project” template. For my project name I used Flurry.Analytics.iOS, but you could use anything.

The default project has a few files in it, we will have a look at each one in depth as we go through the binding steps:

  • ApiDefinition.cs (this is for the generated .NET interfaces from Objective Sharpie)
  • AssemblyInfo.cs (the usual assembly information attributes)
  • Extras.cs (this is for any additional changes that are needed for the bound types)
  • StructsAndEnums.cs (this is for any extra types that you wish to include in the final assembly)

Creating the Initial Binding

This step will involve using Objective Sharpie to get us started, but we will almost always have to go in and tweak a few things.

So, first things first, open Objective Sharpie and start the wizard. Select the Flurry.h header file, and I used the namespace Flurry.Analytics. After saving your file somewhere, we can start the tweaks. I don’t save the result into my solution as the amount of tweaks needed is high enough that I like to have a before and after file. Also, this library is very small. But, there is no reason why you couldn’t just save over the ApiDefinition.cs file in you project.

Before we start, here is a snippet from the Flurry.h file:

    // an enum
    typedef enum {
        FlurryLogLevelNone = 0,
        FlurryLogLevelCriticalOnly,
        FlurryLogLevelDebug,
        FlurryLogLevelAll
    } FlurryLogLevel;

    // the main class
    @interface Flurry : NSObject {
    }
    // ...
    + (void)setAppVersion:(NSString *)version;
    + (NSString *)getFlurryAgentVersion;
    + (void)startSession:(NSString *)apiKey;
    // ...
    @end

In this snippet of Objective-C goodness, there is an enum named FlurryLogLevel and an @interface named Flurry. This will translate into a C# enum and class respectively. It is also good to note that all the methods on this particular type will be static.

The generated C# for this snippet is:

    // the enum
    public enum FlurryLogLevel : [unmapped: unexposed: Elaborated] {
        None = 0,
        CriticalOnly,
        Debug,
        All
    }

    // the main class
    [BaseType (typeof (NSObject))]
    public partial interface Flurry {
        // ...
        [Static, Export ("appVersion")]
        [Verify ("ObjC method massaged into setter property", "Flurry/Flurry.h", Line = 61)]
        string AppVersion { set; }

        [Static, Export ("getFlurryAgentVersion")]
        [Verify ("ObjC method massaged into getter property", "Flurry/Flurry.h", Line = 80)]
        string GetFlurryAgentVersion { get; }

        [Static, Export ("startSession:")]
        void StartSession (string apiKey);
        // ...
    }

As you can see, the generated file is similar, but not quite the same.

Tweaking the Generated Binding (ApiDefinition.cs)

After we generated our C# files, there are several things to note:

  • This code doesn’t compile at all
  • A good few of our methods are set to properties, especially note the setter-only ones
  • There is a [Verify(...)] attribute which doesn’t even exist
  • Some [Export] attributes have a value that ends in a colon (:), and others do not
  • The type is not a class but an interface
  • The base type is specified as a [BaseType] attribute
  • The enum has the item prefixes removed

This is quite a list here, but not all are bad. Objective Sharpie can’t generate perfect code as Objective-C is not C#, so there will always be human intervention. In these cases, it will generate what it thinks to be best and then let you know.

The [Verify] attribute is one way that Objective Sharpie lets you know that it changed something. In this instance, it is letting us know that it changed the setAppVersion method into a property. This is because usually there is both a getter and a setter method for a Objective-C property. But in this case, it is actually a method.

As you may note, these properties have a slightly different [Export] attribute in that these members don’t end in a colon. This is valid for Objective-C property setters, but as this is a method, we should add a colon back. It is also valid for methods that take parameters.

So, to fix those properties, remove the [Verify] attribute. We should also fix the exported name, and for the setter property, add the colon back in.

    [BaseType (typeof (NSObject), Name = "Flurry")]
    public partial interface FlurryAgent {

        [Static, Export ("setAppVersion:")]
        void SetAppVersion (string version);

        [Static, Export ("getFlurryAgentVersion")]
        string GetFlurryAgentVersion ();

        [Static, Export ("startSession:")]
        void StartSession (string apiKey);

    }

As you can see here, I corrected the SetAppVersion write-only property by transforming it into a void method that exports to setAppVersion:. Note the full name and colon as this method takes a parameter.

Also, I needed to fix the GetFlurryAgentVersion read-only property by transforming it into a string method that exports to “getFlurryAgentVersion”. Note the lack of colon as this method takes no parameters.

And finally, I decided I wanted my final class to be called FlurryAgent to avoid confusion with the namespace as well as indicate that it was the Agent. In order to do this, All I needed to do was to rename the type and add the Name property in the attribute with a value of "Flurry".

The reason for adding this property is, after changing the type name, the binding no longer will be able to find the underlying Objective-C type. Usually the binding will use the default name if none is provided, the C# class name. After changing it, it no longer reflected the Objective-C type name, hence the new property.

Managing the Structures and Enumerations (StructsAndEnums.cs)

The last thing to fix, in the generated code, is the enum.

This is simple to do, just remove the strange attribute-like bit: [unmapped: unexposed: Elaborated].

One of the nice things of Objective Sharpie is that it removes the enum prefixes and just uses the relevant bits. For example the original item was FlurryLogLevelNone, but this is now just None.

The final enum looks like this after it has been moved to StructsAndEnums.cs:

    public enum FlurryLogLevel {
        None = 0,
        CriticalOnly,
        Debug,
        All
    }

So far, all our generated code has been moved into either, ApiDefinitions.cs (the class), or StructsAndEnums.cs (the enum). We are still not complete yet, but we are nearly there.

Additional Binding Code (Extras.cs)

Once we have the basic binding done, we can always extend what the native library provided with extra features. This is done by adding new source files to the project.

For example, if for some reason you need to add any extra bindings to the library, say to access a private member or even just to make the new API cleaner and more .NET-like.

For example you could do something like this:

    public partial class FlurryAgent : NSObject {
        public static void LogTimedEvent (string eventName, Action action) {
            try {
                FlurryAgent.LogEvent (eventName, true);
                action(); // do our task
            } catch {
                FlurryAgent.EndTimedEvent (eventName, null);
                throw;
            }
        }
    }

What is happening here is that I am adding a new method to the final .NET assembly. This method can make use of the methods in the API definition interface. In this particular example, I am adding a method that can take an Actionand make sure that we fire a ‘starting’ and then an ‘ending’ event to the Flurry servers. This is a new bit of functionality that can be baked right into the binding assembly.

Working with the Native Library (.a)

This step is actually quite easy, just add the native library (.a) to the project, and you are almost done.

When you add the native library to the project, Xamarin Studio will create a new .linkwith.cs file that matches the library name. For example with Flurry, I added the libFlurry_5.2.0.a library to my project and it generated a libFlurry_5.2.0.linkwith.cs.

This new file is the last bit that needs to be done. It is for the linker when using this library in an iOS app. It usually will contain only a single line, a single [LinkWith] attribute. This attribute allows you to specify what targets this library can be used with, what extra iOS frameworks are needed, etc:

    [assembly: LinkWith (
        "libFlurry_5.2.0.a", 
        LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7 | LinkTarget.ArmV7s, 
        ForceLoad = true)]

This is the default line, split for readability, and usually it is all that is needed. What this does is say that the linker must use the libFlurry_5.2.0.a native library as well as this library can be used on the Simulator and all the devices. The ForceLoad is used by the Xamarin.iOS linker, and specifies a linker flag. According to the documentation, this should always be true for now.

But just before we finish up, we need to add any required frameworks. Without this, there will be strange happenings…but different depending the configuration.

If building for Debug, the app will launch, but nothing will happen at all. The methods can be called and everything, but no actions will take place.

If building for Release, the linker will throw an error:

Error MT5211: Native linking failed, undefined Objective-C class: _OBJC_CLASS_\$_Flurry.
If ‘_OBJC_CLASS_\$_Flurry’ is a protocol from a third-party binding, please check that it has the [Protocol] attribute in its api definition file, otherwise verify that all the necessary frameworks have been referenced and native libraries are properly linked in.

This error is giving us lots of information for @protocol, but as we don’t have any in our project (recall the @interface), we can safely ignore the first part of the second message and focus on the ‘frameworks’ part. According to the Flurry documentation, the Security.framework is required and the SystemConfiguration.framework is optional, but recommended.

So, I added both frameworks, using the Frameworksproperty:

    [assembly: LinkWith (
        "libFlurry_5.2.0.a",
        LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7 | LinkTarget.ArmV7s, 
        ForceLoad = true, 
        Frameworks = "SystemConfiguration Security")]

As shown here, the frameworks are space-separated and do not have the .framework extensions.

Finishing Up

So far we have defined our API, added any additional logic or types, added the native library, set up the linker and specified the frameworks. This is all that is needed, so our library should build fine now and we should be able to use it in an Xamarin.iOS app:

    // the methods
    FlurryAgent.StartSession("PQSZJRK4B5BW8Q7YQQXF");

    // the properties that we changed back into methods
    FlurryAgent.GetFlurryAgentVersion ();

    // the extra method that we added
    FlurryAgent.LogTimedEvent ("started", () => {
        // ...
    });

Under the Hood

One thing to know is that the iOS binding project is actually not really compiled directly, but are a series of stages. Each file actually has a different build action.

The first stage to building the binding is to build a reference assembly with the files:

  • ApiDefinition.cs (with build action ObjcBindingApiDefinition)
  • StructsAndEnums.cs (with build action ObjcBindingCoreSource)

Next, this assembly is then reflected to generate the actual binding code. This generated code is then compiled with the rest of the files:

  • Extras.cs (with build action Compile)
  • StructsAndEnums.cs (again with build action ObjcBindingCoreSource)
  • libFlurry_5.2.0.linkwith.cs (with build action Compile)
  • libFlurry_5.2.0.a (with build action ObjcBindingNativeLibrary but is actually just a resource)

An example of the generated code in the second stage, the interface member void StartSession(string) is actually used to generate a big block of code:

    [Export ("startSession:")]
    [CompilerGenerated]
    public static void StartSession (string apiKey)
    {
        if (apiKey == null)
            throw new ArgumentNullException ("apiKey");
        var nsapiKey = NSString.CreateNative (apiKey);

        MonoTouch.ObjCRuntime.Messaging.void_objc_msgSend_IntPtr (class_ptr, selStartSession_Handle, nsapiKey);
        NSString.ReleaseNative (nsapiKey);
    }

This is all the magic that happens under the hood to redirect values from the managed .NET to the underlying native library.