Categories
Xamarin

Building a Better Button

I’ve used the Xamarin.Forms Button in a number of projects and while it has slowly improved (adding support for images etc) it’s still lacking in a few areas. Recently I needed to add support for wrapping and truncation options and these are mysteriously absent from the stock control.
For inspiration I looked at the Label control as this has a LineBreakMode property which allows you to use a variety of truncation or wrapping modes. This seemed perfect and rather than re-invent the wheel I set about adding the same property to the Button. Both iOS and Android support these options via LineBreakMode and Ellipsize properties respectively. Along the way I found it was necessary to improve the logic on iOS for sizing to fit content and the InTheHand.Forms.FormattedButton was born. I was also able to use this opportunity to fix a niggly issue with the iOS button where it fitted the label to the full width of the button so if you used a background the text was jammed against the left/right edges which looks ugly.
It’s intuitive to use from XAML:-

<cc:MyButton LineBreakMode="WordWrap" Text="This is a wrapping button with no other special properties set just a single long descriptive text value"/>

The new control is in the GitHub project and the NuGet package.

Categories
Windows 10

Adventures in Desktop App Conversion

The Desktop App Converter (or Project Centennial) is a way of packaging up traditional desktop applications in appx format for the Windows 10 store. You would commonly use it for modernising an existing app. This allows you to take advantage of store distribution and incrementally add modern functionality to it.

My requirement was a little different. I needed a way of adding functionality to a UWP app which is not currently possible via UWP. The functionality in question was the ability to show a progress bar on the desktop taskbar entry. If you don’t know what I mean by this it is what you get with many desktop installers or other apps which make large downloads to keep you informed of progress while you do something else. There are two ways of approaching this – you can include a desktop “full-trust” component inside the same app package as a UWP app allowing you to mix and match and submit to the store as a single entity but this requires the developer to get full trust certification each time you repeat the process. The other approach is to build a standalone desktop bridge app to call the Win32 APIs necessary to control the taskbar and have other UWP apps call into this via an API. This way once the enabling app has gone through certification subsequent UWP apps can make use of it without any special permissions. Underneath there is a simple Uri scheme to request taskbar changes and so the caller won’t throw an error if the “Taskbar Progress” app isn’t installed.

 

taskbar test (2)
Taskbar Progress in a UWP app

 

The API to call this is already part of Pontoon as the InTheHand.UI.ViewManagement. StatusBarProgressIndicator. This mirrors the API in UWP which is only available on phone devices. We wrap the functionality for you so there is a common API across mobile and desktop flavours of Windows as well as Android and iOS (although iOS is limited to a indeterminate spinner).

I have a very basic sample app which I’m just waiting to convert from private to public in the store and will update this post with a link when published.

Get Taskbar Progress from the Windows Store

Pontoon on GitHub

Categories
Xamarin

InTheHand.Forms Updates

I’ve updated the InTheHand.Forms NuGet package with a few new features:-

  • .NET Standard support.
  • Stretch property to define how to handle cropping/zooming of the video to fit the MediaElement size.
  • NaturalVideoWidth and NaturalVideoHeight allow you to adjust your UI based on the actual aspect ratio of a video file at runtime.
  • Removed obsolete OnPlatform2 as the Xamarin OnPlatform has now been updated to support additional platforms.
Categories
Bluetooth Windows

Read iBeacons from UWP

I recently got some estimate beacons and have been trying out various things with them. By default they are configured to support Apple’s iBeacon format and could be used in an iOS app to provide location awareness in a close environment. You can read the same data from UWP and can add some location/context awareness in this way. In this post I’ll just discuss the iBeacon approach.

In UWP development there is a BluetoothLEAdvertisementWatcher which is used to read advertisement data from nearby Bluetooth Low Energy devices. The watcher fires the Received event for each advertisement found and you can read the data as required. The key to using iBeacon is to understand how the data is encoded. Advertisement sizes are limited so they need to be designed to be as compact as possible while providing enough information to uniquely identify each device. The iBeacon format consists of a UUID (Guid) and two unsigned short integers. These should be thought of as a hierarchical format:-

UUID > Major > Minor

A location aware app would use a unique UUID for its own use, for example a chain of stores. The Major id would then represent an individual store and the Minor id a location within that store. In iOS the raw iBeacon advertisements are “hidden” from the CoreBluetooth API and instead exposed by CoreLocation. In UWP we use the BluetoothLEAdvertisementWatcher and reconstruct the elements of the beacon. These are stored in a ManufacturerData section with Apple’s manufacturer id (0x4C) used. Within this we access the raw data as an iBuffer (WinRT/UWP equivalent of a byte[] array). The DataReader class is used to sequentially read through the data. The data is:-

Byte 0 – type – 2 for iBeacon

Byte 1 – data length: 21 bytes for iBeacon

Bytes 2-17: UUID

Bytes 18-19: Major ID

Bytes 20-21: Minor ID

We must be careful to respect the byte ordering of the Guid element, the following Gist wraps up the operation:-

public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
_watcher = new BluetoothLEAdvertisementWatcher();
_watcher.Received += _watcher_Received;
_watcher.Start();
}
private void _watcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
foreach(BluetoothLEManufacturerData md in args.Advertisement.ManufacturerData)
{
if(md.CompanyId == 0x4C) // Apple
{
DataReader reader = DataReader.FromBuffer(md.Data);
byte advertismentType = reader.ReadByte(); // 0x02 – iBeacon
byte len = reader.ReadByte(); // 0x15 (21) – iBeacon
int a = reader.ReadInt32();
short b = reader.ReadInt16();
short c = reader.ReadInt16();
byte[] d = new byte[8];
reader.ReadBytes(d);
Guid uuid = new Guid(a, b, c, d);
ushort major = reader.ReadUInt16();
ushort minor = reader.ReadUInt16();
Debug.WriteLine(uuid + " " + major + " " + minor + " " + args.RawSignalStrengthInDBm);
}
}
}

view raw
App.xaml.cs
hosted with ❤ by GitHub

The event also gives you the Rssi, you can use this to make a general assumption about the relative distance of multiple beacons but should not assume a direct measurement of distance from it.

Categories
Bluetooth GitHub

Migrating Wiki content from CodePlex to GitHub

I’ve seen a few articles on migrating your projects from CodePlex but they kind of ignore the Wiki and suggest just copying and pasting the text across. There is a way which will copy the entire contents and only require a little manual work. The instructions below are the steps I took to migrate the 32feet documentation across. There were 76 files in total so much easier that copying and pasting!

First from the Home page of your CodePlex project you’ll see a button “Download Wiki” in the page toolbar. Click this to download a Zip file containing all the documents and supporting attachments for your Wiki.

migrate-wiki-1

This contains two folders, one in raw CodePlex format and the other (called “docs”) in Markdown. You’ll want the Markdown version. There are two standard files in this folder – Home.md is the homepage – the equivalent to your Readme on GitHub. This one you’ll probably want to copy and paste into a Readme.md file in your new repository. The Documentation.md is the entry point into your documentation Wiki. I removed the Home.md after copying the contents and renamed Documentation.md to Home.md as this is now the entry point into the Wiki documentation. If there are hard links back from child pages these may require fixing.

migrate-wiki-2.png

In your GitHub project go to the Wiki tab and you’ll see an option on the right “Clone this wiki locally”. You can then use Visual Studio or any Git tool of your choice to work on a local clone of the Wiki repository.

migrate-wiki-3.png

This should be empty for a new GitHub project. Once you’ve done this you can copy all the Markdown and attachment files you downloaded and unzipped from CodePlex into this folder. Commit and Push this git repository and you’ve uploaded a (mostly) working Wiki to your new site.

After doing this I noticed a couple of issues which required further changes. Firstly the inline code examples were broken:-

migrate-wiki-4

A bit of digging revealed a slightly different “tag” for code in GitHub markdown which should be:-

migrate-wiki-5

Another quick fix was that GitHub requires tables to have a preceding blank line otherwise it just renders as raw text full of pipes.

The last big formatting issue was the main Wiki page uses a number of anchors to various points in the table of contents and this was broken in conversion. It appears that there are automatically generated anchors for top level headers only. It is possible to workaround (although it feels dirty) by using inline HTML A tags e.g. replace

{anchor:General Bluetooth Data Connections}

with

and link to it using

[General Bluetooth Data Connections](#user-content-general-bluetooth-data-connections)

I hope this helps you as you migrate your own projects from CodePlex.

Categories
Windows 10 Xamarin

GitHub Latest

While I prepare to refresh my main machine with Windows 10 Creator’s Update and the latest Visual Studio and Xamarin updates I thought I’d throw together a summary of open-source progress since I last blogged:-

Since the announcement of CodePlex’s upcoming retirement I’ve been moving projects across to GitHub. 32feet and my Compact Framework archive are now moved, there is just some tweaking to be done on the Wiki content for the former. I’m planning a blog post on the process I’ve used.

I’ve reworked the existing documentation site which was hosting the Pontoon documentation and it now also contains InTheHand.Forms and 32feet documentation. The Compact Framework stuff may follow but it depends on getting the dependencies setup just right for the help file builder.

Pontoon has had a number of enhancements. I’ve been refactoring the code to better handle the number of different platforms which are supported. This has also allowed me to identify gaps and fill some of them. Android now has InTheHand.Devices.Radios support for Bluetooth and the ability to launch any StorageFile with Launcher.LaunchFileAsync. macOS now has full support for local and roaming settings as-per iOS.

Categories
Bluetooth Windows 10

Talking to Printers

Recently I’ve been working with a selection of Bluetooth printers. During this work I’ve noticed an odd thing about the UWP Bluetooth APIs. It’s all about the Class of Device. These are a set of defined device types and are categorised into major and minor classes. For example a Printer has a Major class of Imaging and a Minor class of Printer. In the raw form the class of device is a bitmask and the bits reserved for the major class define the behaviour of the rest of the bits. The UWP API exposes a BluetoothClassOfDevice class and this has two properties – MajorClass and MinorClass and each uses an Enumeration. The interesting thing with this approach is that the MinorClass values overlap but have different meanings depending on the major class. There are already multiple fields with the same value – ComputerDesktop, PhoneCellular and PeripheralJoystick for example. For whatever reason all of the Imaging minor classes are missing – they all pre-date the original WinRT codebase so really should have been included.

I created a gist to pull together my helper method and enum to make identifying printers a little easier. I created an extension method to return the correct minor class when you identify a device with a major class of imaging:-

using System;
using Windows.Devices.Bluetooth;
namespace InTheHand.Devices.Bluetooth
{
/// <summary>
/// Defines missing values in the <see cref="BluetoothMinorClass"/> enumeration for devices with a <see cref="BluetoothClassOfDevice.MajorClass"/> of Imaging.
/// </summary>
[Flags]
public enum BluetoothImagingMinorClass
{
Uncategorized = 0,
Display = 4,
Camera = 8,
Scanner = 16,
Printer = 32,
}
/// <summary>
/// Provides an extension method to get the Imaging minor class.
/// </summary>
public static class BluetoothClassOfDeviceExtensions
{
/// <summary>
/// Returns the Minor Class of Device for an Imaging device.
/// </summary>
/// <param name="classOfDevice"></param>
/// <returns></returns>
public static BluetoothImagingMinorClass GetImagingMinorClass(this BluetoothClassOfDevice classOfDevice)
{
return (BluetoothImagingMinorClass)((int)classOfDevice.MinorClass);
}
}
}

Categories
Xamarin

Forms Previewer and Custom Controls

Recent versions of Xamarin include the Forms Previewer which generates a live representation of your XAML as it will appear on iOS or Android. I noticed one slight problem when working on my MediaElement control…

The Android renderer instantiates a MediaController object. This is a standard Android class but the Forms Previewer would throw an exception any time my control was placed on a page. The exception popup is not very friendly either – it truncates text and has no method to copy the text to the clipboard.

forms-previewer-error
Forms Previewer Exception

 

I needed a way to determine if the code was running in the Forms Previewer and to just fake it and not create the native control. This will render a grey box for the MediaElement which frankly is fine with me to get the layout right. It turns out that in the absence of an IsDesignTime equivalent property there is a simple way to tell if your code is executing in a real app or not – and it’s the same as Silverlight (remember that?). Simply check if Application.Current is null inside the OnElementChanged method. If there is a current application you can render the control normally, if Current is null then don’t call the code to create the control.

if (Application.Current != null)
{
     // create native control here..
}

The iOS renderer also uses a native control (AVPlayerViewController) but doesn’t present the same issue so this workaround wasn’t necessary there.

Categories
Xamarin

Playing Media with Xamarin Forms

Xamarin Forms has quite a rich set of controls which work natively across platforms however a big gap in the functionality is the ability to play audio or video content.

You can create custom controls for Xamarin and from the platform-specific renderers you have full access to the APIs provided by that platform to create complex controls of your own. However on a couple of projects I’ve needed to display a video and it felt to me like a fairly standard control we take for granted when doing “native” development.

The good news is that you don’t have to do this yourself because I’ve put my control up onto GitHub and NuGet and it’s ready to roll for Android, iOS and of course Windows UWP. If you’ve used the Windows MediaElement you already know how to use it 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:MediaPlayerSample"
xmlns:forms="clr-namespace:InTheHand.Forms;assembly=InTheHand.Forms"
x:Class="MediaPlayerSample.MainPage">
<StackLayout>
<forms:MediaElement HorizontalOptions="Fill" VerticalOptions="Center" HeightRequest="240" x:Name="Media" AreTransportControlsEnabled="true" Source="http://video.ch9.ms/ch9/334f/891b78a5-642d-40b4-8d02-ff40ffdd334f/LoginToLinkedinUSingXamarinAuth_mid.mp4"/>
</StackLayout>
</ContentPage>

view raw
MainPage.xaml
hosted with ❤ by GitHub

Simply add the InTheHand.Forms NuGet package and add a namespace to your XAML and add the MediaElement control. You can do the basics straight from XAML, but you can add a Name to the control and interact with it from the code too. There is full documentation for the control online. If you have any issues/feature suggestions please post them to GitHub.

The player controls can be toggled using the AreTransportControlsEnabled property. The displayed controls will match the native appearance of the target platform. For example the sample above uses a link to a Channel9 video on Xamarin Auth by @HoussemDellai and you can see below how it is rendered on an Android app and a UWP desktop app:-

screenshot_20170301-220605mediaplayer-uwp

I’ve also been working on support for the ms-appx scheme for Source Uris allowing you use a common way of referring to files in the application package. This should be in the next NuGet release (after 1.0.2017.301) along with a legacy Windows Phone 8.1 renderer.

I hope you find this useful in adding media to your Xamarin Forms projects!

Categories
Windows 10

All New Clipboarder

My free Clipboarder app for Windows Phone has now (finally) been re-written as a universal Windows 10 app. It’s currently available across all Windows 10 platforms (except Xbox but that seems fairly logical!). The app provides a share target allowing you to share data from modern apps to the clipboard to be pasted into any app (old or new, doesn’t matter as long as it has text input). A new feature made possible by using UWP is roaming content across devices. You can share something to your clipboard on your phone and then use it from the Clipboarder app on your desktop PC. The app still supports the clipboard Uri scheme in case you’ve been using it for clipboard access in Windows Phone 8.1 (appx) apps.

Download from the store (Free):-

https://www.microsoft.com/store/apps/9wzdncrdkj7j