Xamarin macOS Binding Libraries

In creating an IOBluetooth binding for Xamarin Mac I learned about Objective Sharpie and binding libraries. There is little documentation on this but it is fairly similar to Xamarin iOS and for that there is a lot more source material. The output from Objective Sharpie gives you binding definitions which you can use in a dll project to produce a binding library you can then call from any other Xamarin dll or app. This was fine to a point but there are issues with some of the complex types used and these cannot always be marshalled automatically. This left me with an API with a few missing bits as I tried and failed to manually adjust the binding via trial and error.

The project sat around untouched for some time but recently I’ve begun to revive it and hope to sort out these bits so it can be released as a complete functioning API for Xamarin Mac. At first I thought I was going to have to create two libraries – one with the raw API calls and another with a clean API over the top but I had missed something buried in the docs and it turns out there is an easier solution.

When you have a binding library it will, by default, have two files – ApiDefinition.cs which contains all the API calls and has a Build action of BindingApiDefinition and a StructsAndEnums.cs which contains (well I’ll let you guess from the name) and this has a Build action of ObjcBindingCoreSource. When the classes are generated from the interface definitions in ApiDefinition.cs they are actually partial classes. This means you can extend them and have additional functionality built cleanly into the library. If you have a particularly messy API call you can mark it as internal and then surface it in a more friendly way from a partial class. To do this add another source file to the library project (I’ve called it Extra.cs because I saw that in a sample but the name isn’t important) and set the Build action to Compile. Here you’ll need to create a partial class with the same name and namespace as the “interface” you want to extend from ApiDefinition.cs, and then add methods, properties etc.

The first time I added this my build failed. I subsequently found out that there is one additional step to tell the binding compiler to ignore this file. Open the project properties, under Build select the Objective-C Binding Build page. Here in Additional btouch arguments box add -x:Extra.cs (or replace with your own filenames). This stops the initial binding compilation from using the partial class, which then gets built normally in the subsequent managed code build. The project should now build and expose the combined functionality. I did find that intellisense often gets confused when editing the partial class because there isn’t another definition of a partial class at this time (remember in ApiDefinition.cs it’s actually an interface). However it seems you can safely ignore this!

This in theory allows you to completely change the API surface which you expose to Xamarin from whatever you started with. I don’t want to go too crazy with IOBluetooth – my feeling is that it should match the native API with a few tweaks for C# naming conventions, using namespaces rather than huge class names, and .NET friendly types where appropriate. Objective Sharpie struggled with some of the enum/constant definitions and so these still require a bit of massaging. It should be obvious how it maps to the native API.

If you have feedback on the API or would like to get involved in getting the library up to release standard please let me know. All the current code is on GitHub in the IOBluetooth and IOBluetoothUI folders.

Update to Xamarin Forms MediaElement

Things are progressing with the Xamarin Forms Pull Request but it’s a big change and I’ve had feedback on how quickly (or not) it’s going. For this reason I’ve decided to post an update to InTheHand.Forms to port some of the advances and compile for Xamarin Forms 4.0. The new release is marked as a pre-release to avoid anyone automatically updating at this stage and hitting problems because there are a few API changes to ease the transition to the future official version.

https://www.nuget.org/packages/InTheHand.Forms/2.0.2019.613-pre

It takes advantage of fast renderers on iOS and Android and has a cleaner communication method between the control and the renderers. I haven’t changed the Source property which is still based on UWP style Uris for special file locations. I haven’t added a WPF renderer even though the Xamarin Forms version will have this (minus some missing platform functionality like HTTPS and overlaid media playback controls). There are some improvements to the API including a Volume property. The original PCL library is removed along with Windows 8.1 and Windows Phone platforms. I will probably continue to use this package as a method to test other renderers (e.g. Mac and Tizen) before embarking on another Pull Request to Xamarin Forms.

I think the plan with the Xamarin Forms pull request was to integrate in 4.1 but it hasn’t progressed into the current preview releases. I’ll keep you posted as I know more.

Xamarin Forms Fast Renderers – Part 2 Android

Following on from Part 1, this post will briefly discuss the Android approach to Fast Renderers. Again there isn’t really any documentation for control builders, but there are examples within the Xamarin Forms source to work from. Xamarin Android like iOS uses an IVisualElementRenderer interface which is very similar to the iOS equivalent. The differences are down to the different platforms approaches. For example the NativeView and ViewController of iOS are represented with the View and ViewGroup properties on Android. ViewGroup can return null, but if the control uses a ViewGroup derived class for laying out controls that can be returned.

There are some additional methods such as SetLabelFor(id) and UpdateLayout(). The first one supports the accessibility system on Android and allows a descriptive label to be added to another control. The latter calls a helper class the VisualElementTracker to help update the layout.

Beyond these things the concept is very much the same and you handle the same kind of interactions with the Element which is the platform agnostic representation of the control and its properties.

Xamarin Forms Fast Renderers – Part 1 iOS

A Xamarin Forms Renderer provides the device-specific logic to display a Xamarin Forms control using platform-native UI. Traditionally this was done using the ViewRenderer<T,T> base class. What this actually creates in the UI hierarchy is two controls – the outer being a basic place-holder providing layout logic and the inner control being the desired native control (e.g. a UITextField in the case of an Entry on iOS).

This introduces overhead into the UI and complicates the layout logic as the whole page is arranged. The concept of a fast renderer does away with the enclosing ViewRenderer and instead requires you to implement an interface with the standard behaviour required by the Xamarin Forms layout system.

When I began re-writing my MediaElement for inclusion into Xamarin Forms I needed to replace the iOS renderer with a fast renderer but there was very little documentation on building a fast renderer. I found looking through the source for other renderers helpful. The Pages and WebView all use fast renderers in the current codebase.

On iOS this interface is IVisualElementRenderer and it exposes a number of properties, an event and a few methods.

Properties:-

  • Element – returns the Xamarin Forms element which this renderer represents
  • NativeView – returns the native UIView-based control
  • NativeViewController – returns the UIViewController which manages the View

Events:-

  • ElementChanged – raised when an Element is assigned to the renderer

Methods:-

  • GetDesiredSize – returns a SizeRequest from a set of constraints. The control can alter this to fit required content for example. An extension method for UIView provides GetSizeRequest which will calculate the SizeRequest based on the constraints and optional minimum width/height.
  • SetElement – assigns the Element and causes the ElementChanged event to be raised. You’ll also hook up the PropertyChanged event here to react to changes in the Element and apply them to the NativeView.
  • SetElementSize – updates the layout to fit a specific size. Normally you call Layout.LayoutChildIntoBoundingRegion() to perform this.

A secondary interface IEffectControlProvider provides a single method to register an effect with the View.

By looking at the existing in-box renderers I was able to understand how they are implemented and re-write the MediaElementRenderer to use this pattern. For reference the full code of the iOS renderer is here in GitHub.

Not all the renderers in iOS use the new approach, I imagine it will be some time before all the existing renderers are re-written. Currently UWP and other platforms still use the traditional approach. I’ll follow up with the Android equivalent soon.

Capture Android Screen Video from Visual Studio

While debugging your Xamarin Android app in Visual Studio you can capture a video of the device screen and upload it to your PC. To do this open the ADB command prompt from the Xamarin Android toolbar:-

adb command prompt

At the command prompt navigate to a folder where you want the video to end up. Type the following command to start recording:-

adb shell screenrecord /sdcard/filename.mp4

The path you supply must be a valid path on the device with enough space to store the video. The video can be up to 3 minutes long. To stop recording press Ctrl-C at the console window. Then to upload the video type:-

adb pull /sdcard/filename.mp4

Where obviously the path must match whatever you used in the first command. Once it shows that the pull was successful you can open the file and do whatever you need to do with it. You can do basic trimming using the Windows Photos app, and there are plenty of other options for more complex editing…

Xamarin iOS App Settings

When we talk about app settings we could mean a few different things. The actual settings values which are stored by your app, an in-app method to view/edit those settings or the iOS Settings UI which exposes both system and application settings to the user in the centralised place.

In this article we’ll look at the last of these. If you are creating a cross platform app you’ll probably never look into this as the main place to store your settings because you’ll want a consistent UI within your app to expose settings. The iOS Settings app will always have an entry for your app anyway as this exposes permissions which your app has requested and allows the user to change their preferences. You may have also noticed that when debugging your Xamarin app you’ll see entries added here for the Xamarin debugger.

In my previous blog post I wrote about visualising screen taps in your app in order to capture video walkthroughs. I decided I didn’t want the option for this exposed via the apps own Settings page, and I wanted to be able to set it before even launching the app, so I looked into adding it to this menu. As it turns out it is actually quite easy. I’m going to assume you use the NSUserDefaults mechanism for storing the underlying setting value. You might use this directly or via a cross-platform API such as Pontoon to abstract this away behind a common API.

First you need to create a folder within your Xamarin iOS project called “Settings.bundle”. Within this, you add an XML file called “Root.plist” and set the Build Action to “BundleResource”. This XML file is in Apple’s horrible “Property List” XML format and contains a dictionary with a single entry with the key “PreferenceSpecifiers”. The value if this is an array of dictionaries, each of which represents an individual preference item. Here is my example adding a single Boolean toggle:-

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
   <dict>
      <key>PreferenceSpecifiers</key>
      <array>
         <dict>
            <key>Type</key>
            <string>PSToggleSwitchSpecifier</string>
            <key>Title</key>
            <string>Show touches</string>
            <key>Key</key>
            <string>ShowTouches</string>
            <key>DefaultValue</key>
            <false/>
         </dict>
      </array>
   </dict>
</plist>

This give you the simple output shown below. The section header with your app name is added for you. Here you can see each entry defines the setting type (which affects other options available), the display text, the key (which is the name of the setting in code), and the default value (of the correct type for your setting).

Visible Touch App Settings

There are other type specifiers for other settings types such as text or selections from multiple fixed values. You can read more details here.

While this might seem a bit disconnected from your app you can open this settings page programmatically. Useful not just for showing the user these custom settings but also if you want to assist the user in turning an app permission back on. There is a hard-coded Uri to launch your app specific settings page which you can call using:-

UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));

Some 3rd-party apps make extensive use of this to display app settings and properties. Take a look at Microsoft Word which uses this mechanism to display product version and licensing information as well as app settings. How much you intend to integrate with it is entirely up to you, but it can help your app feel more integrated when it offers these kinds of hooks into the OS.