Category Archives: Xamarin

Using A Custom Icon Font in Xamarin.Forms

Anyone who has done much mobile development work knows the pain of managing multiple bitmaps for devices with different screen resolutions. It’s a particular bugbear for Android developers due to the plethora of different devices available and the fact that Google’s default method of choosing appropriate resources (screen density) is not always an accurate indicator of screen size.

It would be much better all round to use vector graphics instead, but as (at the time of writing) native support for SVGs on both iOS and Android is patchy at best it’s no surprise that there’s no vector graphics support in Xamarin.Forms.

Fortunately there’s a decent workaround for monochrome vector graphics – use a custom font instead. You can either use an existing icon font such as Google’s excellent Material Icons set or the ones from Font Awesome, or use a tool such as IcoMoon which enables you to create your own font from SVG files created in Illustrator or similar.

So here’s how you do it, for the purposes of this tutorial we’re going to be applying Google’s Material Icons font to the Xamarin.Forms.Label control but the same approach can be used for different fonts and controls (e.g. Xamarin.Forms.Button).

You can download a .zip file for the project here.

1. Create A Custom Control
Just so we don’t get confused we’re going to create our own subclass of Xamarin.Forms.Label called IconLabel. Add a new empty class file to your shared project like so…

using System;
using Xamarin.Forms;

namespace CustomFontDemo
{
	public class IconLabel:Label
	{
		public IconLabel ()
		{
		}
	}
}

This custom IconLabel will work exactly like a standard Xamarin.Forms.Label on the whole, but for the purposes of this tutorial I’m going to add an instance of it to the page that the default Xamarin.Forms app creates at startup. The resulting XAML looks like this..

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
			 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
			 xmlns:local="clr-namespace:CustomFontDemo" 
			 x:Class="CustomFontDemo.CustomFontDemoPage">
	<local:IconLabel Text="Welcome to Xamarin Forms!" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

Nothing remarkable here, if you run the app at this point it should operate exactly like the default Xamarin.Forms app. Now we’re going to get the icon font to work which requires a bit of platform-specific tinkering

2. Import Your Custom Font Into Your iOS Project
Right-click on the Resources directory in your iOS project and select ‘Add Files’. Navigate to the font file you have chosen on your hard drive and add it to the project. Once the file has been added right-click on it and check the ‘Build Action’ is set to ‘BundleResource’.

mockup_3x
Where To Import The Font File On iOS

Now select your ‘info.plist’ file and click the ‘Source’ tab. Right-click anywhere in the editor and select ‘New Key’. You need to change the name of the key from ‘Custom Property’ to ‘UiAppFonts’ and then add an entry where it says ‘String’ for the file name of your font. In this instance ‘materialicons.ttf’.

mockup_3x
Info.plist Settings On iOS

3. Write A Custom Renderer For iOS
Custom renderers are used when you want to override the default behaviour for a particular UI component on a particular platform. In this case we are overriding the default renderer for our IconLabel class to use the font we have just imported.

Add an empty class file to your iOS project and edit like so…

using System;
using UIKit;

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

// This informs the compiler that we're using this class to render an IconLabel on this platform
[assembly: ExportRenderer (typeof (CustomFontDemo.IconLabel), typeof (CustomFontDemo.iOS.IconLabelRenderer))]

namespace CustomFontDemo.iOS
{
	public class IconLabelRenderer : LabelRenderer
	{
		public IconLabelRenderer ()
		{
		}

		// sets the font for the platform-specific ui component to be our custom font
		protected override void OnElementChanged (ElementChangedEventArgs e)
		{
			base.OnElementChanged (e);

			double? fs = e.NewElement?.FontSize;
			// Note we're using the font family name here, NOT the filename
			UIFont font = UIFont.FromName ("Material Icons", (int)fs);
			Control.Font = font;
		}

		// Without this strange things happen if you update the text after the label is first displayed
		protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			base.OnElementPropertyChanged (sender, e);
			if (e.PropertyName.Equals ("Text"))
			{
				Label label = sender as Label;
				// Note we're using the font family name here, NOT the filename
				UIFont font = UIFont.FromName ("Material Icons", (int)label.FontSize);
				Control.Font = font;
			}
		}
	}
}

4. Set The Text To The Appropriate Icon
Any custom icon font should come with documentation showing which icon maps to which unicode text character. Usually this is done with HTML-encoded values. For the purposes of this demo I’m going to use the value for the ‘favourites’ icon in Google’s Material Icons font. I can reference this directly in the XAML like so, note I’ve alse increased the font size for the label here too!

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
			 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
			 xmlns:local="clr-namespace:CustomFontDemo" 
			 x:Class="CustomFontDemo.CustomFontDemoPage">
	<local:IconLabel Text="&#xE87D;" VerticalOptions="Center" HorizontalOptions="Center" FontSize="144"/>
</ContentPage>

Alternatively you can set the text in code using the WebUtility.HtmlDecode() method in the System.Net namespace.

Text = System.Net.WebUtility.HtmlDecode ("&#xE87D;");

Running the above code should give you a label displaying an icon from your custom icon font in iOS. To get things running in Android we have a similar (though slightly different) procedure.

5. Import Your Custom Font Into Your Android Project
Right-click on the Assets directory in your Android project and select ‘Add Files’. Navigate to the font file you have chosen on your hard drive and add it to the project. Once the file has been added right-click on it and check the ‘Build Action’ is set to ‘AndroidAsset’.

mockup_3x
Where To Import The Font File On Android

6. Write A Custom Renderer For Android
Add an empty class file to your Android project and edit like so…

using System;
using Android.Graphics;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

// This informs the compiler that we're using this class to render an IconLabel on this platform
[assembly: ExportRenderer (typeof (CustomFontDemo.IconLabel), typeof (CustomFontDemo.Droid.IconLabelRenderer))]

namespace CustomFontDemo.Droid
{
	public class IconLabelRenderer : LabelRenderer
	{
		public IconLabelRenderer ()
		{
		}

		// sets the font for the platform-specific ui component to be our custom font
		protected override void OnElementChanged (ElementChangedEventArgs e)
		{
			base.OnElementChanged (e);
			// Note we're using the filename here, NOT the font family name
			var font = Typeface.CreateFromAsset (Forms.Context.ApplicationContext.Assets, "materialicons.ttf");
			Control.Typeface = font;
		}
	}
}

And that should be job done – you now have scaleable vector-based icons using a custom font running on both iOS and Android in Xamarin.Forms!

You can download a .zip file for the project here.

mockup_3x
Custom Icon Font Running On Xamarin.Forms iOS

mockup_3x
Custom Icon Font Running On Xamarin.Forms Android

How To Use Google Maps In Xamarin.Forms

Recently I’ve been putting together an app development proposal for a potential client. It’s the sort of app that I think would suit Xamarin.Forms very well, only it has a large mapping component for which the client wants to use Google Maps on both Android and iOS.

At the time of writing the ‘built in’ Xamarin.Forms Map view has limited functionality and defaults to using Apple Maps on iOS. This makes it unsuitable for this project which meant I had to find and (roughly) test out an alternative before I could put a proposal together with any degree of confidence.

I managed to get it working in the end, but not without hitting all sorts of snags which I’ll document here in the hope it might make the process easier for someone else. Most of this information is scattered about the web but it’s difficult to find it all in one place.

1. Find A Suitable Library
Fortunately there’s a third-party open source Google Maps API in development for Xamarin forms which you can access here. Xamarin.Forms.GoogleMaps seems to be pretty full-featured so, rather than trying to reinvent the wheel, this is what I decided to use. Thanks very much to GitHub user amay077 for making this available.

2. Get It To Compile
Once downloaded from GitHub the next step is to get the Xamarin.Forms.GoogleMaps sample project to compile. This was pretty straightforward apart from a few error messages – you may run into the following on iOS:

This version of Xamarin.iOS requires the iOS 10.2 SDK (shipped with Xcode 8.2) when the managed linker is disabled. Either upgrade Xcode, or enable the managed linker. (MT0091) (XFGoogleMapSample.iOS)

To get round this either upgrade Xcode (groan) or do what I did and go to Project Options->Build->iOS Build and set linker behaviour to ‘Link Framework SDKs only’ which should fix it (you may have to clean and rebuild).

On Android you may get something like the following:

Could not find android.jar for API Level 23. This means the Android SDK platform for API Level 23 is not installed. Either install it in the Android SDK Manager (Tools > Open Android SDK Manager…), or change your Xamarin.Android project to target an API version that is installed.

A rare helpful error message this – to fix either do as the message says and go to Tools->SDK Manager and install the appropriate level SDK or go to Project Options->Build->General and select an SDK that you do have installed (I set it to Android 5.0 and it worked fine).

3. Install Google Maps On A GenyMotion Device
OK – I’m going to assume that a) you want to use an emulator for development and b) you are using GenyMotion as it’s by far the fastest. If you try and run the Xamarin.Forms.GoogleMaps sample project as is you will probably see a grey square where the map should be with ‘Xamarin.Forms.GoogleMaps’ in black text. This is because Google Play Services (which includes Google Maps) is not installed on GenyMotion by default. To do this I followed the instructions here (scroll down the page to where it says ‘Setup Google Play Services’). I was using an Android 5.0 GenyMotion device and did not need to do the first step (ARM Translation Installer).

Once you have flashed your virtual device you will get all sorts of irritating popup messages saying ‘Google Play Services Has Stopped’ and the like but if you just soldier on through this and update google play services and google maps via Google Play you should be OK. If you can get the standard Google Maps app running on the device you are sorted.

4. Create An Android API Key
So, assuming you have Google Maps running OK on your GenyMotion emulator, if you now try and run the Xamarin.Forms.GoogleMaps sample project you will just get what looks like a blank map (or a ‘barren featureless desert’ for Black Adder fans). This is because you haven’t supplied a valid API key – if you look through the Application Output of the app in Xamarin Studio you will see something like the following:

Authorization failure. Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map.
In the Google Developer Console (https://console.developers.google.com)
Ensure that the “Google Maps Android API v2” is enabled.
Ensure that the following Android Key exists:
API Key: your_google_maps_android_api_v2_api_key
Android Application (;): FF:4B:77:38:AB:3A:F3:A8:42:CC:03:27:74:AA:CB:5F:66:A1:5F:D0;net.amay077.xfgooglemapsample

Copy the long hex string (SHA-1 certificate) and package name from this error message as this will save you faffing around with keystore commands later.

Now go to your Google Developer Console. On your Dashboard click ‘Enable API’ and select the Google Maps Android SDK. Now go to ‘Credentials’, click on ‘Create Credentials’ and select ‘API Key’ followed by ‘Restrict Key’.

You should now get a list of restriction options. Select ‘Android apps’ and enter the package name and SHA-1 certificate from the error message I told you to note down earlier. The API key can now be saved.

Note that you will have to enable access for both the ‘Debug’ and ‘Release’ versions of your app as they are signed differently and therefore have a different SHA-1 certificate. Simply run the app in both configurations and grab the application output as above to get the appropriate SHA-1 key for each.

Whilst you’re at it you may want to create an iOS API key (see step 5). It takes a few minutes for these to take effect so, once done, I suggest you go and make yourself a well-earned cup of coffee.

Now you need to embed your API key in your app. The way I suggest doing this is consistent with all the documentation on the matter – go to your AndroidManifest file and enter the following inside the tag:

<meta-data android:name=”com.google.android.geo.API_KEY” android:value=”YOUR_API_KEY” />
<meta-data android:name=”com.google.android.gms.version” android:value=”@integer/google_play_services_version” />

Replace ‘YOUR_API_KEY’ with your actual API key of course. Now your manifest file should look something like this:

<manifest xmlns:android=”http://schemas.android.com/apk/res/android&#8221; android:versionCode=”1″ android:versionName=”1.0″ package=”net.amay077.xfgooglemapsample”>
<uses-sdk android:minSdkVersion=”15″ />
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION” />
<uses-permission android:name=”android.permission.ACCESS_LOCATION_EXTRA_COMMANDS” />
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION” />
<uses-permission android:name=”android.permission.ACCESS_CHECKIN_PROPERTIES” />
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />
<uses-permission android:name=”android.permission.ACCESS_MOCK_LOCATION” />
<uses-permission android:name=”android.permission.INTERNET” />
<application android:label=”OpenHouse”>
<meta-data android:name=”com.google.android.geo.API_KEY” android:value=”AIzaSyDJ7qxHOOh_4A1PodKyU0MlkhFIsyZsNJ7″ />
<meta-data android:name=”com.google.android.gms.version” android:value=”@integer/google_play_services_version” />
</application>
</manifest>

Just one more step – in the Xamarin.Forms.GoogleMaps sample project the API key isn’t entered in this way so you will need to delete the ‘dummy’ API key that been placed there. Do do this simply open MyApp.cs and remove the following line:

[MetaData(“com.google.android.maps.v2.API_KEY”,
Value = Variables.GOOGLE_MAPS_ANDROID_API_KEY)]

Hopefully if you now rebuild and run the Android project, and you’ve waited long enough for your API key to activate, you should now be able to see Google Maps correctly displayed in the GenyMotion emulator. Well done – it’s not the simplest process in the world!

5. Create An iOs API Key
This is pretty much the same process as creating your Android API key. Go to your Google Developer Console. On your Dashboard click ‘Enable API’ and this time select the Google Maps iOS SDK. Again go to ‘Credentials’, click on ‘Create Credentials’ and select ‘API Key’ followed by ‘Restrict Key’. This time choose iOS app restriction and enter the bundle identifier from your Info.plist file. For the Xamarin.Forms.GoogleMaps sample project it’s ‘net.amay077.xfgooglemapsample’.

To embed the API key into your iOS application open AppDelegate.cs and pass the API key as a string in the call to Xamarin.FormsGoogleMaps.Init(). This should be all you need to get the app running on iOS.

6. Embed The Xamarin.Forms.GoogleMaps API In Your Own Projects
Assuming you’ve managed to run the sample project successfully it should be fairly simple to get the API working in your own Xamarin.Forms projects. Xamarin.Forms.GoogleMaps is in NuGet so, in a new Xamarin.Forms solution, right-clicking on the ‘packages’ folder and selecting ‘Add Package’ will allow you to add references to the Xamarin.Forms.GoogleMaps packages. Remember to add them to every project in your solution. You may need to enable ‘show pre-release packages’ in the NuGet browser in order to download versions that are consistent with the sample projects.

If you run into strange issues, such as XAML errors when setting properties on a Xamarin.Forms.GoogleMaps.Map view or ‘Could Not Resolve Type’ and ‘BadImageFormatException’ errors when trying to position the map then you most likely have an incompatible version of the various packages somewhere. Check that all your package references (both to Xamarin.Forms and Xamarin.Forms.GoogleMaps) are consistent in all of your projects and ideally the same as the sample project.

I hope this article saves you some of the pain and grief I endured whilst trying to get all the stuff to work. If it does I always appreciate more followers on Twitter here!

mockup_3x
FAIL – Google Maps Not Installed On GenyMotion Emulator

mockup_3x
FAIL – No Valid Google Maps API Key

mockup_3x
SUCCESS – Xamarin.Forms.GoogleMaps Working on GenyMotion Emulator

Jetboard Joust Devlog #30 – Crossed Platforms

Porting From Mobile To PC with MonoGame
This week I was supposed to have started on the initial gameplay testing for Jetboard Joust but I came up against a rather nasty snag.I develop using Xamarin Studio on a Mac and had been using the GenyMotion Android emulator for my main testing platform. This probably seems strange given that my main target platform is PC, but GenyMotion generally runs extremely well and I don’t want to have to buy another machine just for development purposes. Unfortunately I discovered a problem with GenyMotion in that it seems to just ‘miss’ some keyup/keydown events. The problem is intermittent but bad enough to make serious gameplay testing on the platform impossible – no response from their support either.

That means I need another platform for testing. The iOS simulators are hopeless for graphics performance (and don’t respond to keyboard control as far as I’m aware), Google’s stock Android emulators take an age to launch/install builds and the Xamarin Android Player, though fast, is still pretty flaky. That left Xamarin.Mac as the only ‘native’ Mac option but there’s a hefty additional licence charge for that (or at least there used to be – I couldn’t quite work out what’s going on with Xamarin.Mac since the Microsoft buyout).

As a result of this tragic state of affairs (remember when Apple used to take x-platform development seriously in the initial OSX days?) I decided the only option would be to ditch Mac native and move to running Windows under VMWare Fusion (at least for any development that requires serious gameplay testing). Quite a change. I’ve done this before for ‘Attack Of Giant Jumping Man’ though so was optimistic that it should be a workable solution, plus I’d have to do the PC port anyway at some point – may as well get on with it.

So I started with a brand new Windows 8.1 VM and a fresh installation of Visual Studio 2015. I’ve been using MonoGame 3.2 up to this point but this was as good a time as any to update to 3.5. Installation of the various components was a breeze. I chose the DesktopGL target as it was most similar to the target I’d worked on for ‘Attack Of Giant Jumping Man’ (so hopefully the few bits of platform-specifc code I’d had to write could be re-used) and it didn’t take too long to get my project to compile. The only problem I ran into was that references to the Microsoft.Xna.Framework.GamerServices namespace couldn’t be resolved. For some reason the reference to the assembly that contains these wasn’t included in the MonoGame template project and had to be added manually (Add Reference->Extensions and then choose the appropriate MonoGame.Framework.Net assembly for the platform you are targeting, its a bit confusing as all the assemblies are named the same in the list so you have to click on each one to see more info).

I’m using the ‘shared folder’ feature of VMWare Fusion to share my source code directory between Mac and Windows – if I import the source files as links then both my Xamarin Studio projects on MacOS and my Visual Studio projects on windows both remain perfectly in sync – nice!

Next step is to import all the content – unfortunately I can’t figure out a way to keep all these files in sync as importing a file as a link from a shared folder doesn’t seem to work in the MonoGame pipeline tool. This is a bit of a bummer but not to much of an issue at the moment – hopefully I can figure something out eventually.

Only issue with the content was that I was getting an error when compiling my custom shader files due to a missing DirectX component (‘d3dcompiler_43.dll’) despite having DirectX 11 installed. I followed the instructions to fix this here (using the second method, not the full install) and all was fine.

So now everything would compile and run. Imagine my joy when, on launching, all I got was the garbage you can see in the GIF on the right. Complete gobbledegook. Spirits totally crushed. What. The. Hell.

I had absolutely no idea what was going on here and no idea where to start debugging. Nothing I thought of initially had any effect. Jetboard Joust runs on MEAT, my own (originally Java-based) 2D gaming platform that has been over ten years in development. MEAT is another layer of abstraction above MonoGame and fairly complex making it difficult to strip things down to MonoGame basics and do a few simple tests but this is clearly what I needed to do.

I decided to run a few simple MEAT tests first and see if I could get anything up and running…

1. Load image and draw sprite
2. Load image and draw sprite with clipping (as if from sprite sheet)
3. Load image and draw sprite with crop (MonoGame ScissorRectangle)
4. Load image, render to offscreen buffer (RenderTarget2D) and then to screen.

…all of these worked fine which was encouraging to an extent but didn’t get me any closer to a solution. However the next test produced some very strange results.

One of the MEAT classes is a graphical font class – a bitmap font and associated metrics data are stored in a single file which can be used to easily render bitmap text to screen. When I tried a test render using one of these graphical fonts the text would appear OK and then mysteriously disappear after around 30 seconds on screen. Bizarre. This mysterious disappearance only happened when my game template code (that handles all the main menus and stuff) had been executed at startup, ie at least 30 seconds before the problem occurred.

So all I could do was to comment out chunks of the game template code, launch the app, and then run a timer for approx 45 seconds to see if the font disappeared – an incredibly tedious process reminiscent of debugging on J2ME handsets. Eventually I narrowed it down to the line of code that was causing the problem – I was reassigning the property originally assigned to the graphical font that was drawn to screen to a different graphical font. Even though this was a mistake on my part there is absolutely nothing ‘wrong’ with this and it wasn’t causing a problem on any other platform. I had to test and retest several times to convince myself that this line of code was the problem but it was – as soon as I didn’t reallocate the property once the font was drawn to screen the test font didn’t disappear and the entire game ran perfectly!

All I can think of is this had something to do with garbage collection of graphics memory. Reallocating the property meant that the garbage collector (incorrectly) thought the memory should be freed which resulted in some kind of graphics meltdown. This would explain why it took around 30 seconds for the problem to appear – it only happened when the garbage collector kicked in. I create the font images using Texture2D.FromStream() rather than the Content.Load() methods in MonoGame which is slightly weird and could be something to do with it as well – I doubt this is as well tested as the Content.Load() methods.

Anyway, one can’t really blame the MonoGame team for missing such an obscure issue and even with the amount of time I wasted over this it was still a pretty fast cross-platform port so kudos to them. Android/iOS to PC in around a day with about 99% of the codebase consistent – not to be sniffed at! Nice to see the issues with the XBox controller fixed in MonoGame 3.5 too!

Dev Time: 1 days
Total Dev Time: approx 32.5 days

previous | next

mockup_3x
Where On Earth Do You Start To Debug This Shit?

Got There In The End – PC, Full Screen, XBox Controller

Updating Legacy MonoGame Projects to iOS9 / Unified API

Just the moment you long for. Apple releases a new iOS update and that breaks something in your development platform of choice (Xamarin/MonoGame in my case) and all your apps no longer work. Great. Like I didn’t have enough to do.

And as with everything Apple nowadays – any kind of update seems to break everything else thereby creating a domino effect of pain and tedium as you wait for gigabytes of data to download over a shitty rural broadband connection. Oh, the joy!

So, without further ado here’s how to update your legacy MonoGame projects to iOS9 and the Unified API. Hopefully this will make life a little easier for someone.

If you have a crappy broadband connection buy a copy of ‘War And Peace’ or something suitable to keep you occupied.

If you’re running an OS earlier than Yosemite update to El Capitan. You’re going to have to unfortunately. You’ll need XCode 7 and that only runs on Yosemite or later. Apple aren’t big on backwards-compatibility these days.

Update to XCode 7.

Update everything Xamarin-related to the latest version. I’m currently running Xamarin Studio 5.10 which at the time of writing is on the alpha update channel. I was getting some issues with creating archives using the current ‘stable’ release.

Update any additional components you are using to the latest version – for example I was using the Xamarin Google AdMob component. Make sure to add the ‘unified’ version.

Open the solution you are updating and try to build it – you may get the following error:

/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets: Error: Error executing task DetectSdkLocations: Unknown TargetFrameworkIdentifier: .NETFramework

Remove the references to monotouch and OpenTK from your project and instead add references to OpenTK-1.0.dll and Xamarin.iOS.dll (these are visible under the ‘all’ tab when you go to edit references).

Try and build the project again. You will probably get a shedload of errors to do with it not being able to find the MonoTouch namespace. Just get rid of all references to MonoTouch, ie replace ‘using MonoTouch.Foundation;’ with ‘using Foundation;’ or ‘using MonoTouch.UIKit;’ with ‘using UIKit;’ etc.

Depending on how many of the native classes you referenced you may have some additional work to do here, probably involving changing ‘float’ references to ‘nfloat’. Hopefully you’re not referencing too many of these as the whole point of MonoGame is that we avoid the native classes if possible (I just had to change some of my ad-serving code).

Hopefully your code should now compile and the only remaining errors (if any) are due to an outdated MonoGame, for example:

Error CS0012: The type `MonoTouch.UIKit.UIImage’ is defined in an assembly that is not referenced. Consider adding a reference to assembly `monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065′ (CS0012)

Download and build the latest version of MonoGame from the Develop branch on GitHub. At the time of writing there are issues with the latest ‘stable’ build of MonoGame (3.4) with iOS9 so you will need the version from the Develop branch. Change all the MonoGame references in your project to the latest versions.

Hopefully you should now get an error free compile, however you may get something like the following:

Error MT0073: The minimum deployment target for iOS is 5.1.1 (current deployment target is 4.2). Please select a newer deployment target in your project’s Info.plist. (MT0073)

To resolve this simply change the deployment target of your iOS project to 5.2 (note: this setting is now in the info.plist file).

Try and compile again. Most likely you will now get the following errors:

Error MT0016: The option ‘–nomanifest’ has been deprecated. (MT0016)

Error MT0016: The option ‘–nosign’ has been deprecated. (MT0016)

To resolve this your .csproj file needs to be changed so that it’s building using the ‘unified’ settings. Bit of voodoo required here as you will have to quit Xamarin and edit the .csproj file for your iOS project using your text editor of choice. Follow the instructions in step one of the ‘Steps To Update Manually’ section here. In short:

Change the project flavor in your csproj files from ‘6BC8ED88-2882-458C-8E55-DFD12B67127B’ to ‘FEACFBD2-3405-455C-9665-78FE426C6842’. Edit the csproj file in a text editor and replace the first item in the <ProjectTypeGuids> element.

Change the Import element that contains ‘Xamarin.MonoTouch.CSharp.targets’ to ‘Xamarin.iOS.CSharp.targets’.

You should now, finally, be able to compile and run your project on a connected iOS device. If, on launch, you get the following error:

System.EntryPointNotFoundException: alcMacOSXMixerOutputRate
at at (wrapper managed-to-native) Microsoft.Xna.Framework.Audio.OpenALSoundController:alcMacOSXMixerOutputRate (double)
at at Microsoft.Xna.Framework.Audio.OpenALSoundController.OpenSoundController () in <filename unknown>:line 0
at at Microsoft.Xna.Framework.Audio.OpenALSoundController..ctor () in <filename unknown>:line 0
at at Microsoft.Xna.Framework.Audio.OpenALSoundController.get_GetInstance () in <filename unknown>:line 0
at at Microsoft.Xna.Framework.iOSGamePlatform..ctor (Microsoft.Xna.Framework.Game game) in <filename unknown>:line 0
at at Microsoft.Xna.Framework.GamePlatform.Create (Microsoft.Xna.Framework.Game game) in <filename unknown>:line 0
at at Microsoft.Xna.Framework.Game..ctor () in <filename unknown>:line 0

You are not running the latest MonoGame build from the Develop branch as described earlier. Unfortunately MonoGame 3.4 and earlier exhibit this problem with iOS9. Update all the MonoGame references in your project to the latest version from the Develop branch on GitHub.

If you’ve made it this far without losing the will to live your app should be running on iOS9. I’m afraid to say your problems aren’t over though. Once you have built your updated app and try and upload to iTunesConnect using the Application Loader you will more than likely run into the following errors:

ERROR ITMS-90086: “Missing 64-bit support. Beginning on February 1, 2015 new iOS apps submitted to the App Store must include 64-bit support and be built with the iOS 8 SDK. Beginning June 1, 2015 app updates will also need to follow the same requirements. To enable 64-bit in your project, we recommend using the default Xcode build setting of “Standard architectures” to build a single binary with both 32-bit and 64-bit code.”

To fix this under Project Options->Build->iOS Build->Supported Architectures select ‘ARMv7+ARMv7s+ARM64’

ERROR ITMS-90474: “Invalid Bundle. iPad Multitasking support requires these orientations: ‘UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown,UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight’. Found ‘UIInterfaceOrientationPortrait’ in bundle ‘com.bitbull.flappingbird’.”
ERROR ITMS-90475: “Invalid Bundle. iPad Multitasking support requires launch story board in bundle ‘com.bitbull.flappingbird’.”

To fix this add a setting’UIRequiresFullScreen’ to your project’s info.plist file and set it to ‘YES’.

Hopefully you should now be good to go and if you got this far without topping yourself – well done! It’s not exactly the most straightforward process in the world!

Creating Bindable Properties in Xamarin.Forms

Something you’re bound to run into sooner or later when developing with Xamarin.Forms is the issue of how to make a property bindable. Fortunately it’s pretty easy to do – though I found it hard to find a simple example online that worked both for setting the property programmatically and via xaml.

So, without further ado here’s an example of a bindable ‘Foobar’ property that can be set both programmatically and via xaml. Just copy/paste this into your own code whilst changing the relevant bits and you should be fine…

Note: ‘YourClass’ should be replaced by the type name of the class that holds the property. References to ‘bool’ should (obviously) replaced by the type of property you are declaring. The ‘false’ value that is passed to the BindableProperty.Create() method refers to the default value for the property and should be replace by something meaningful.

public static readonly BindableProperty FoobarProperty=BindableProperty.Create<YourClass,bool>( p => p.Foobar, false );

public bool Foobar
{
	get 
	{ 
		return (bool)GetValue(FoobarProperty); 
	}
	set 
	{
		SetValue(FoobarProperty, value); 
	}
}

private void UpdateFoobar()
{
	// Do whatever you need to do when the property 
	// has been set here. By the time this method is
	// called Foobar will already hold the updated value
	// so if you need to reference the old value you will
	// need to store it in a class variable
}

protected override void OnPropertyChanged(string propertyName)
{
	base.OnPropertyChanged(propertyName);

	switch( propertyName )
	{
		case "Foobar":
			UpdateFoobar();
			break;
	}
}

Hopefully that’s been helpful – now why not take a brief break from work to watch our trailer for ‘Attack Of Giant Jumping Man’…


Attack of Giant Jumping Man

Unhelpful Exceptions In Xamarin.Forms

if you’re wondering why it’s been so quiet around here recently it’s because I’ve had my head down working on a contract project using Xamarin Forms – as well as trying to get #superjp finished. Life is busy. Too busy.

Anyway, Xamarin Forms is pretty cool once you get the hang of it – but to start with things were very painful. Documentation is sparse and often wrong, then when crashes happen exceptions are usually thrown deep within the bowels of some auto-generated code leaving you with little or no idea what the issue is. And that’s when you get an exception at all – often the exceptions are unhelpfully caught and just ‘glossed over’, leaving you with absolutely no idea why your code isn’t executing.

So I thought I’d jot down a few posts covering issues I’ve run up against which may prevent someone from tearing their hair out quite as much as I had to over the first couple of weeks – first up is weird crashes and unhelpful exceptions.

1. Autofac.Core.DependencyResolutionException

An exception was thrown while invoking the constructor ‘Void .ctor(IAuthenticationService)’ on type ‘MenuService’. Argument cannot be null.

This exception often appears after changing properties in the XAML. It appears to be the result of a bug in Xamarin Forms and was always thrown in the same place in our code. Simply building/running again stopped the exception from appearing. Annoying to say the least – but once you’ve added a comment to remind you it’s not your fault you learn to live with it.

2. Error: The type `SomeType’ already contains a definition for `someProperty’
This is a compile time rather than a runtime error and is caused by creating properties in your ‘code behind’ class that have the same names as controls in the associated XAML (x:Name=”someProperty”). Always give your custom properties/class variables unique names – Xamarin.Forms seems to use the ‘x:Name’ property for variable names in generated code and this is what causes the conflicts.

A similar issue can cause errors at runtime if you have a named control (x:Name=”SomeProperty”) that conflicts with a type name in the same namespace or one of the imported namespaces. It’s probably good practice to define your own naming convention for XAML controls so that you are sure they don’t conflict with any properties, types or variables in any accessible namespace.

3. Xamarin.Forms.Xaml.XamlParseException: Property Content is null or is not IEnumerable
This one is probably obvious to those with prior experience of XAML but to noobs like me it wasn’t and caused much weeping and gnashing of teeth. You can’t have more than one Layout at the top level of a ContentPage (or ScrollView, whatever). This makes sense when you think about it (how would it know how to layout the Layouts) but the exception doesn’t give much clue as to what’s going on so can lead to confusion.

4. Xamarin.Forms.Xaml.XamlParseException: No Property of name ‘Foobar’ found
Assuming the class to which you’re referring actually has a property of name ‘Foobar’ (or whatever) then the most likely cause of this is that the property is not bindable. I’ve given a simple example of how to make a property bindable here. Most of the properties within the Xamarin.Forms classes have already been made bindable but if you do run into one that’s not you can most likely create a subclass that contains a bindable version of the property you want to access (just set the appropriate property in the base class).

This error can also be caused by duplicate name issues as describe in 2 above.

5. The name InitializeComponent does not exist within the current context
If you’re running Forms as a shared project with iOS as the target the most likely reason for this error is that you don’t have ‘Use MSBuild Build Engine’ checked under Project Options->Build->General.

Another cause of this error can be mistakenly not having your XAML class definition ( x:Class=”Foo.Bar”) matching the class definition in your ‘code behind’ class. I made this mistake a number of times when using copy/paste to set up XAML files.

I may add more here later…

Windows Phone Development On A Mac With MonoGame

This week I have been porting ‘Toss The Floppy Frog’ (my first Android and iOS title with MonoGame) to Windows Phone 8 – and it has been painful. Very painful. So painful that I though I’d write a simple step-by-step guide to the process of porting iOS and Android MonoGame titles to Windows Phone. Hopefully this will ease the pain for others.

Part of the suffering has, no doubt, been due to the fact that I am a complete Windows noob. I have been developing on a Mac since around 1995 and have barely touched a Windows machine since then – I even wrote my own JavaME emulator (running on J2SE) so I could do JavaME development on a Mac! Windows, and all its terminologies and conventions, is very much uncharted territory for me.

The largest chunk of pain has, though, been due to what are in my opinion three key deficiencies in the Windows Phone implementation of MonoGame. These are…

1. The Project Templates Are Broken
The MonoGame project templates provided with the 3.2 install don’t work with Visual Studio 2013 (which is the latest version at the time of writing). I don’t know about previous versions. The basic template doesn’t launch the game correctly and doesn’t get to the ‘cornflower blue’ screen we so long for. No errors are given, it just doesn’t work. This issue caused me around half a day of tearing hair out before I found a post on the MonoGame forum that gave a solution (see the ‘step by step’ guide below). If these templates could be fixed I’m sure it would save a lot of developers a lot of grief and avoid casting MonoGame in an unnecessarily bad light.

2. The Content Pipeline Requirement Sucks
I understand the requirement for a content pipeline, really I do. Optimising your assets for use on different platforms is a great idea, but it should be exactly that – part of the optimisation process, NOT a requirement for getting a basic game up and running. The fact that ‘raw’ image and sound assets can’t be loaded in the Windows Phone implementation of MonoGame but can in the Android and iOS versions kind of makes a mockery of the whole ‘Write once, play anywhere’ mantra. Many developers (myself included) will have games that run perfectly fine without the need for content pipeline optimisations and the requirement to use one is just an unnecessary barrier to ‘getting stuff done’.

3. The Content Pipeline Itself Sucks
I couldn’t get any of the MonoGame content projects to load correctly in Visual Studio 2013 and I was unable to find any information online as to how to get the Monogame content tools to work correctly without these. the MonoGame content tools were completely useless to me. Fortunately someone on the MonoGame forums pointed me to an open-source XNB compiler that I was able to edit (ie hack) to convert all my assets to XNB (see the ‘step by step’ guide). That’s at least a day of pain right there. Frankly, if I hadn’t have been pointed to this tool I probably would have given up (and I hardly ever give up).

Now I have the greatest respect for the MonoGame project and team – they have given and continue to give their time for free to provide an awesome product for the IndieDev community. The criticisms above are given in the hope that these areas of MonoGame will be improved which will lead to more developers adopting the platform and more fun/revenue for all of us. Hopefully they’ll be taken in that spirit.

And, once you’ve got past the pain, there is one gigantic plus to all of this, and that is…

100% code re-use!!

Yes, you read that right. Once I was able to iron out a couple of quirks I was able to get 100% resuse of my game code across Android, iOS and Windows Phone. That’s pretty much the holy grail of cross-platform coding and an extremely big upside! The only platform specific code is in the app-launcher stubs and about three lines in my image loader. Nice.

So, without further ado, on to the step by step guide to porting iOS/Android MonoGame titles to Windows Phone using a Mac…

1. Prepare Your Code For Windows Phone
If, like me, you’re more familiar with a Mac and Xamarin Studio than Windows/Visual Studio it’s easiest to get this out of the way before you even touch Windows. Here are the issues I came across:

System.Collections.Hashtable is not available on Windows Phone.

References to this class can be replaced easily by references to:

System.Collections.Generic.Dictionary<Object><Object>

Note that there is a slight ‘gotcha’ here in that Hashtable will return null when trying to retrieve a value for a key that doesn’t exist whereas Dictionary will throw an exception. Your code may need to be altered to account for this.

System.Collections.ArrayList is not available on Windows Phone.

References to this class can be replaced easily by references to:

System.Collections.Generic.List<Object>

System.Runtime.Remoting package is not available on Windows Phone.

If you use this package you will have to work around this somehow. I was using it for dynamic class instantiation and could quite easily replace it by hard-coded calls to instantiate the relevant classes.

The following MonoGame properties return incorrect values on Windows Phone:

GraphicsDeviceManager.PreferredBackBufferWidth
GraphicsDeviceManager.PreferredBackBufferHeight

GraphicsDevice.DisplayMode.Width
GraphicsDevice.DisplayMode.Hight

If you are using any of these to get display width/height the following alternative seems to work:

GraphicsDevice.Viewport.Bounds.Width
GraphicsDevice.Viewport.Bounds.Height

Texture2D.FromStream() is not implemented in MonoGame for Windows Phone.

Bummer. If you are using this (as I was) you will have to work around it. I caught the System.NotImplemented exception and loaded the relevant asset(s) using the content manager instead. I really hope this gets implemented soon as it’s an important function.

Assets are loaded without the file suffix.

On Android/iOS you will probably be using something this:

Content.Load(“myimage.png”)

to load assets which will have to change to:

Content.Load(“myimage”)

on Windows Phone. Ideally write code that catches the exception and tries the alternative method if the first attempt fails.

2. Install Some Kind Of Virtual Machine
You probably want either VMWare Fusion or Parallels. I used Fusion which seems OK though it took quite a bit of farting around to get the ‘shared folder’ feature (which allows you to access files on your ‘host’ mac from the ‘guest’ PC) to work.

3. Set Up The Virtual Machine And Install Windows
Set up an x64 virtual machine and install a 64bit version of Windows otherwise the Windows Phone emulators won’t work. I’m still running a 32bit version of Windows which means I have been unable to launch the emulators so far – I’ve been using an actual device for testing. I believe it must also be the ‘pro’ version of Windows in order for the emulators to work.

4. Install Visual Studio 2013 Twice(!)
From here. You want both the ‘Windows’ version (for Windows Phone) and the ‘Windows Desktop’ version (for the content pipeline stuff). Fortunately both will reside happily side-by-side (unlike my children).

5. Install MonoGame 3.2
From here. May well have been updated since this was written.

6. Install XNA
You will need this for the content pipeline stuff. Follow the instructions and use the PowerShell script kindly provided here.

7. Install Windows Media Player
If it’s not there already – some versions of Windows install it by default, some don’t. You’ll need it for audio processing in the content pipeline and it can be downloaded from here.

8. Set Up A New MonoGame Solution
Launch Visual Studio for Windows and choose the ‘MonoGame Windows Phone’ project template uncder ‘Visual C#’ templates. If it’s not there you need to check MonoGame has installed properly. Call the project something sensible (e.g. the name of your app) and save it anywhere.

9. Update The MonoGame Packages
This is necessary to fix the broken MonoGame template issue and must be done with a solution open in Visual Studio. Launch the NuGet console under Tools->NuGet Package Manager->Package Manager Console and type in the following:

PM: Install-Package MonoGame

This will update the template. It asks if you want to overwrite a few files – click ‘yes’ to each one but ‘no’ to ‘Game1.cs’ as this file will have been altered to reference your app’s namespace.

10. Check For ‘Cornflower Blue’
Now you have done this you should be able to build/run the project and get our old friend the ‘cornflower blue’ screen on your chosen emulator or device. Well done! It took me about a day to get to this point!

11. Import Your Source Code
Having wasted a lot of time trying to get Visual Studio to reference files on my Mac I came to the conclusion that this is impossible. Unlike Xamarin Studio, Visual Studio won’t let you import files as links – they have to reside within the project directory, so the simple-but-far-from-ideal solution is to copy the files from your Mac to the host PC and import. Note that you can ‘copy’ directories from within Windows Explorer and ‘paste’ into Visual Studio which I found the easiest way to import a lot of files at once.

12. Compile Your Source
Hopefully if you followed the suggestions in step one your source just compiles at this point. If not you will have to fix any errors, unfortunately I can’t tell you what these might be as I covered everything I came across in step 1!

13. Convert Your Content To XNB
This should be possible just by using the MonoGame tools but I never succeeded. I had to download an open-source XNB compiler tool from here, open in Visual Studio Desktop, then compile and run to convert my files. It works OK, but the tool only appears to allow you to add one file at a time. Thankfully it was fairly easy for me to modify the code to allow all files in a directory to be added and I’ve included my edited source here. The tool successfully converted PNG, JPG and WAV files for me. If you get an error regarding a missing .dll whilst trying to covert audio you probably need to install Windows Media Player as described in step 7. Whilst MP3 files seem to convert OK I haven’t managed to get them playing correctly yet but I will update this post if and when I do.

14. Import Your XNB Files Into Visual Studio
These go in the ‘Content’ directory exactly as you’d have them organised for iOS or Android. Once imported select the files and under ‘properties’ set ‘build action’ to ‘content’ and ‘copy to output directory’ to ‘copy always’.

15. Change The Template Code To Start Your Game
In Visual Studio find the GamePage.xaml file. Click the little disclosure triangle next to it to reveal GamePage.xaml.cs. Edit this file to replace references to the Game1 with references to your Game class.

16. Run Your App
Congratulations, assuming you followed the tips in stage 1 about loading assets your app should now run on device or emulator. It took me almost three days to get to this point!

I hope this guide is of help to someone – any suggestions for improvement just let me know!

Toss The Floppy Frog – Feels Like My Life’s Work


cornflower
Not Since Yves Klein Has A Blue Square Seemed This Exciting

floppy
At Last – Frog Tossing On Windows

iOS Rate App URL Links In MonoGame / Xamarin

So, in the aim of trying to get a simple ‘rate me’ type link working in Floppy Frog I’ve been trawling the Internet and wading through the usual plethora of conflicting information. It really is surprising that such a simple and necessary piece of functionality isn’t better documented or supported by Apple.

Anyway, the best I could come up with is the following (using info from various sources). This should work in pretty much every version of iOS. Seems Apple did something weird with iOS 7 which they then fixed with iOS 7.1.

The ‘id’ parameter is the numeric app id which you can get from iTunes connect. The ‘Purple Software’ parameter in the second URL, whilst it looks like something that should be changed, is actually some weird Apple thing that needs to stay there. Bizarre, I know.

Note that this will NOT work in the iOS Simulator. Hope this helps someone…

using MonoTouch.Foundation;
using MonoTouch.UIKit;

public void RateApp( string id )
{
	String url;
	float iOSVersion = float.Parse(UIDevice.CurrentDevice.SystemVersion);

	if (iOSVersion >= 7.0f && iOSVersion < 7.1f)
	{
		url = "itms-apps://itunes.apple.com/app/id"+id;
	}
	else
	{
		url = "itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id="+id;
	}
	UIApplication.SharedApplication.OpenUrl(new NSUrl(url));
}

And just for some gratuitous search engine bait, here’s some cool Flappy Bird Videos.

Creating App Promo/Demo Videos With Adobe Premiere

One of the things I’ve had to do with Floppy Frog is create a promo video for uploading to YouTube. I’ve made many promo videos for my JavaME apps and games but these were very simple and I’ve never had to do them in a YouTube-friendly format.

I used to use iMovie for promo videos until Apple changed it from a very simple, flexible and useable tool into the pile of arcane, prescriptive and utterly useless garbage that it is now. For the last few years I’ve been using Apple’s Quicktime 7 pro which, ironically, was much more suited to task than the ‘new and improved (read ‘ruined’) iMovie.

But, Quicktime 7 Pro was not going to cut it (pun intended) for this task so I decided to try Adobe Premiere. Overall I found it a good application for the task in hand though getting the settings right was somewhat time consuming, I’ll therefore detail the process here.


1. Capturing The Video

I thought initially that I’d capture video from the iOS Simulator. Bad idea. It runs much too slowly. Next attempt was to run Floppy Frog on the iPad and capture using Reflector as an Airplay Receiver. Again, bad idea. Frame rate was OK but quality wasn’t up to scratch.

Third attempt was to run the Android version of Floppy Frog using the GenyMotion emulator and capture using the excellent Snapz Pro. Success! GenyMotion runs Floppy Frog just as fast as it would on device and Snapz Pro is a highly configurable and useable screen capture tool. It even captured the audio without a hitch. Had to purchase the full version of GenyMotion to get rid of the ‘free for personal use’ message but I don’t begrudge them that as it’s a fantastic piece of software at a reasonable price.

GenyMotion also has the benefit of being able to configure device display height/width so you can set up a virtual device that’s ideal for the video format you want to capture. In this case my video will run on YouTube at HD 1280*720. Floppy Frog is a portrait game so I wanted a device size that wouldn’t look too ‘squished’ within the HD landscape frame, therefore I set up a virtual device of 600*720 and captured at this size at 30fps which is the frame rate at which the game runs.


2. Import The Video Into Premiere

You’d expect this bit to be easy, and it is easy to simply import the captured video into Premiere. Where I ran into difficulties was that Premiere organises all video into a ‘sequence’ and setting up a ‘sequence’ that matched my video capture settings seemed impossible. All I could do was choose from a series of preset sequences and changing the preset sequence settings was not allowed for some reason. The key issue was that none of the preset sequences ran at 30fps, only 29.97 fps and when Premiere attempted to match my 30fps captured video to the 29.97 sequence settings I was getting horrible interlacing effects.

The solution was to start the Premiere project with any old sequence settings, import the captured video, then select the captured video and choose ‘New Sequence From Clip’. This creates a new sequence matching the captured video settings exactly. Only issue was my video was captured at 600*720 and I wanted a video running at 1280*720! Solution: capture a few seconds of random 1280*720 30fps video using Snapz Pro, import into Premiere, then create the sequence from this. The 600*720 video can now be dragged into this new sequence no problem and the 1280*720 capture can be deleted from the project.

Next issue (which most people probably won’t run into) is that my sound hardware runs at a 48khz sample rate whereas my video was captured at a 48khz sample rate. For some reason Premiere seems pretty flaky about converting between the two (whatever the project Audio settings) so I had to make sure my captured video was saved with the audio running at a 48khz sample rate.

3. Export The Video For YouTube

Once the video is comped together in Premiere it has to be exported at high-quality for uploaded to YouTube. I got and tweaked ‘export media’ settings from a YouTube tutorial and they might be slightly overkill quality-wise but I’ve added screenshots on the right…

4. Sit Back And Watch The Traffic Roll In

Or maybe not. But here’s the finished product anyway…

premiere_vid_youtube
Adobe Premiere YouTube Video Export Media Settings.

premiere_audio_youtube
Adobe Premiere YouTube Audio Export Media Settings.

Floppy Frog – Don’t Flap, Hop!

Recently it has become abundantly clear that the JavaME platform, from which I’ve been deriving a living for more than ten years, is no longer going to be viable platform for a mobile gaming company to support, let alone rely on for a main income stream.

In Spring this year I decided to take the plunge and port all of my library code to Xamarin/Monogame so that, going forward, I can (in theory) develop across the Android, iOS and WinPho platforms with pretty much a single codebase.

There were a number of reasons for choosing Xamarin over other cross-platform solutions such as Marmalade, but the key one was the ability to code in C# which would make the porting of my extremely large (you may read ‘bloated’) existing codebase significantly easier.

I can’t say the process has been easy – there has been much weeping and gnashing of teeth, but overall I am pleased with the Xamarin/Monogame solution. The ‘single codebase’ promise is working out in practice and I find C# a great language to work with.

My first game built ‘from the ground up’ for Monogame has just been released on the App Store and Google Play. Floppy Frog is a deliberately challenging endless jumpy platformer inspired by the likes of Frogger, Flappy Bird, Doodle Jump and Paper Toss, though without being a ‘clone’ of any of these. It’s available for free, currently monetized with AdMob ads. The game is very simple but I’m very pleased with it.

Give it a go – download for iOS or Android. Any positive reviews/ratings are of course much appreciated!