Categories
Windows 10 Windows Phone

Interactive Toasts and Windows Phone 8.1

Windows 10 brings a whole range of new APIs and functionality for building apps. However in the phone space it’s important to be mindful that there are a lot more Windows Phone 8.1 devices in use than Windows 10. Many (but not all) will get an update to Windows 10. A lot of clients are keen on supporting 8.1 to cover the largest group (as an 8.1 app will just run on 10). Of course your users on Windows 10 may miss out on cool features in this way unless you are prepared to maintain both 8.1 and 10 versions of your app. There are a number of areas of the Charming Apps libraries which support “lighting-up” of functionality. That means exposing Windows 10 APIs to Windows 8.x projects. In some cases this is a remapping of existing functionality from an old-style API to one which is source compatible with UWP. In other cases there is functionality which is just not there on 8.x but you can make it available when your app is run on a Windows 10 device.

In order to support this a bit of Reflection is required but we’ve hidden that messy stuff for you – you just call the same APIs and get graceful failure or the “light-up” experience when running on Windows 10. For many of these APIs the Charming Apps library provides iOS and Android implementations while exposing the same UWP API surface. There are a number of possible ways of detecting whether the device at runtime is running Windows 10. One of these is to use:-

if (InTheHand.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 1))

Another is to check:-

InTheHand.Environment.OSVersion.Version

(caveat – On 8.x we can return only Major.Minor.0.0 versions)

One of the new features in Windows 10 is the interactive toast notification. There is no API change to set these locally – it just requires a different XML template. So once you’ve checked your OS version you can switch between a traditional dumb toast or an interactive one such as:-

string xml = "<toast launch="yourstring"><visual><binding template="ToastGeneric" ><text>Big text</text><text>smaller text</text></binding></visual>"
                    + "<actions><input id="time" type="selection" defaultInput="2"><selection id="1" content="Breakfast"/><selection id="2" content="Lunch"/><selection id="3" content="Dinner"/></input>"
         	    + "<action activationType="foreground" content="Primary Action" arguments="primary"/><action activationType="foreground" content="Secondary Action" arguments="secondary"/></actions>"
                    + "</toast>";

Notice that I’ve specified foreground activation. In a UWP project you’d also have the option of background activation where a background task is launched to carry out an action. In the case of foreground activation the system calls your app’s OnActivated method. However this is where it gets a bit more fun. The ActivationKind is not specified in Windows Phone 8.1, nor is the ToastNotificationActivatedEventArgs which is passed through. However the value of ActivationKind.ToastNotification is documented as 1010. The event args contains two items of interest, the Argument – the action which was selected and UserInput which is a string keyed dictionary of input id and selection id or input id and text entered in the case of a text field. I’ve added the following code in my OnActivated method to build up a string containing these values which can be passed to the applications main page using rootFrame.Navigate:-

	    string navigationParameter = null;

            switch (args.Kind)
            {
                case (ActivationKind)1010: //ToastNotification:
                    StringBuilder sb = new StringBuilder();
                    sb.Append(args.GetType().GetRuntimeProperty("Argument").GetValue(args).ToString());
                    IDictionary<string,object> selections = (IDictionary<string,object>)args.GetType().GetRuntimeProperty("UserInput").GetValue(args);
                    if (selections.Count > 0)
                    {
                        sb.Append("?");
                        foreach (KeyValuePair<string, object> pair in selections)
                        {
                            sb.Append(pair.Key + "=" + pair.Value.ToString() + "&");
                        }

                        //remove trailing &
                        sb.Length -= 1;
                    }
                    navigationParameter = sb.ToString();

                    break;
            }
This is just another way of adding value to the user while still maintaining a Windows Phone 8.1 codebase. If you later update your app to Windows 10 it’s very easy to do without much alteration to your code. You don’t even have to go as far as adding interaction to your toasts but you could use this technique of detecting the OS version and simply use the new toast templates.
There are other areas of the Charming Apps libraries which “light-up” when running on Windows 10. For example there is a UWP style Clipboard API which just works on Windows 10 whereas the separate Clipboarder app is required for Windows Phone 8.1 (not Silverlight).

 

Categories
Windows Phone Xamarin

WinRT specific properties in Xamarin Forms XAML

Xamarin Forms originally supported iOS, Android and Windows Phone Silverlight applications. The OnPlatform<T> class provides a mechanism for putting values directly into your XAML which are dependent on the host platform. This is often necessary to cope with different screen sizes and scaling behaviour across platforms. When Windows 8.1 and Windows Phone 8.1 were later added the OnPlatform class was not updated. This means that if you use OnPlatform it can’t provide a value for WinRT platforms. Without resorting to changing properties in the code-behind we wanted a way to set platform specific property values from XAML. Luckily the solution was quite simple – just 55 lines of code including doc comments and I’ve published the code here:-

namespace InTheHand.Forms
{
/// <summary>
/// Replacement for Xamarin.Forms.OnPlatform which supports the Windows (WinRT) platforms.
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class OnPlatform2<T>
{
public OnPlatform2()
{
Android = default(T);
iOS = default(T);
WinPhone = default(T);
Windows = default(T);
Other = default(T);
}
public T Android{ get; set;}
public T iOS { get; set; }
public T WinPhone { get; set; }
/// <summary>
/// The value to use for WinRT (Windows Phone 8.1 and Windows 8.1).
/// </summary>
public T Windows { get; set; }
/// <summary>
/// Currently unused.
/// </summary>
public T Other { get; set; }
public static implicit operator T(InTheHand.Forms.OnPlatform2<T> onPlatform)
{
switch(Xamarin.Forms.Device.OS)
{
case Xamarin.Forms.TargetPlatform.Android:
return onPlatform.Android;
case Xamarin.Forms.TargetPlatform.iOS:
return onPlatform.iOS;
case Xamarin.Forms.TargetPlatform.WinPhone:
return onPlatform.WinPhone;
case Xamarin.Forms.TargetPlatform.Windows:
return onPlatform.Windows;
default:
return onPlatform.Other;
}
}
}
}

view raw
OnPlatform2.cs
hosted with ❤ by GitHub

To use in your XAML you just need to add an XML namespace declaration to your root node (e.g. ContentPage)

xmlns:forms="clr-namespace:InTheHand.Forms;assembly=YOURASSEMBLY"

Then use the class from your XAML. It works with any type which can be represented as a string in XAML. e.g.

<Grid.Padding>
   <forms:OnPlatform2 x:TypeArguments="Thickness" iOS="5" Android="5" Windows="0,10,0,5"/>
</Grid.Padding>
Categories
Windows Phone Xamarin

Windows Phone 8.1 Support in Xamarin Forms

Recently Xamarin Forms has been expanded to support Windows Phone 8.1 and Windows 8.1. There are instructions online for adding a Windows Phone 8.1 app to your solution and plugging it all together here:-

http://developer.xamarin.com/guides/cross-platform/xamarin-forms/windows/getting-started/phone/

However there is a small omission which will lead to a build error – #6 tells you to remove the PhonePage base class from your MainPage definition but you actually need to replace it with:-

public sealed partial class MainPage : Xamarin.Forms.Platform.WinRT.WindowsPhonePage

WindowsPhonePage contains the LoadApplication method which you add in #7.

The instructions for Windows 8.1 require the same tweak except using WindowsPage instead of WindowsPhonePage

Categories
Bluetooth Windows Phone

Background Bluetooth Services on Windows Phone 8.1

Added in Windows Phone 8.1 was a new RfcommConnectionTrigger which allows you to host a Bluetooth service on the device and have your background task triggered when an incoming connection is established. This makes a lot of sense as having to have your app in the foreground to receive connections limits the usage somewhat.

In its simplest form you just need to specify an RfcommServiceId for your service, register your background task and the system publishes the required SDP record which allows other devices to discover your service. Your background task is executed when an incoming connection is received and you can cast the TriggerDetails of the received IBackgroundTaskInstance to an RfcommConnectionTriggerDetails. This gives you two useful things – RemoteDevice – a BluetoothDevice which describes the device which initiated the connection and Socket a StreamSocket which allows you to talk to the remote device.

This works well for most devices but what if you have more specific requirements for the published SDP record. In a foreground app you’d use RfcommServiceProvider and this allows you to set individual SDP attributes which are appended to the default record. The RfcommConnectionTrigger mechanism provides something similar but there is literally no documentation on how it is expected to work. The difference from the foreground approach is that rather than setting attributes with id and raw body it has a property called SdpRecord which accepts an iBuffer. It’s very easy to get from a byte array to an iBuffer but we still have to create the SDP record…

At first I thought the best approach was to look at what the default record contained – but unless you assign a record the property returns null (even once the background task is registered and the SDP record is published). The only way to see the exposed record is to read it remotely from another Bluetooth device (one which is a desktop app since device and service discovery is not supported from WinRT). I used Alan’s SdpBrowserDesktop app from 32feet.This showed a fairly standard set of attributes:-

• Record:
AttrId: 0x0000 -- ServiceRecordHandle
UInt32: 0x10009
AttrId: 0x0001 -- ServiceClassIdList
ElementSequence
    Uuid16: 0x1101 -- SerialPort
AttrId: 0x0004 -- ProtocolDescriptorList
ElementSequence
    ElementSequence
        Uuid16: 0x100 -- L2CapProtocol
        UInt16: 0x3
    ElementSequence
        Uuid16: 0x3 -- RFCommProtocol
        UInt8: 0x6
( ( L2Cap, PSM=Rfcomm ), ( Rfcomm, ChannelNumber=6 ) )
AttrId: 0x0005 -- BrowseGroupList
ElementSequence
    Uuid16: 0x1002 -- PublicBrowseGroup

The ServiceRecordHandle is allocated by the host device as is the Rfcomm channel (here 6). If I want to add a service name to this I realised I would have a problem – how can I build a record when I don’t yet know the port that will be assigned (and there is never a way to find this out from WinRT). I built the record anyway hoping that the system would simply read it and replace the value at registration. You get an ArgumentException at the point you call BackgroundTaskBuilder.Register() and it doesn’t contain any useful information. I tried a few variations of this approach and then happened upon another approach – what if I build a valid record but just for the attributes I want to add. Luckily this approach works – your custom attributes are appended to the end of the record and registration succeeds.

I’m documenting this here because there isn’t a way to add to the MSDN documentation and hopefully someone searching will find the answer. I’m working on porting code across so that there is a friendly API available for all current Windows flavours which helps in reading and writing SDP records and attribute values. I can only assume the approaches used by the foreground and background APIs differ because they were written at different times by different teams.

My custom record consists of an ElementSequence, with a 16bit UUID for the attribute (0x0100 – ServiceName) followed by a UTF-8 encoded string e.g.

Element Sequence
   Uuid16: 0x0100
   String (len 11): "Hello World"

Windows 10 supports this same approach and it is no longer for Phones only – it should be universal across phones, desktop and IOT so I anticipate people doing more advanced things with Bluetooth…

Categories
Windows Phone

Bluetooth HID on Windows Phones

Microsoft have already announced that Bluetooth HID (keyboard) support is finally coming in Windows 10, but it was quietly added in Windows Phone 8.1 GDR2. The problem is this update won’t be circulated to most phones. It is however present on the new Lumia 640 series. WP_20150511_19_41_09_Pro

It’s very easy to setup a Bluetooth Keyboard with your phone once you’ve paired the devices you just type when you’re in an app which accepts text input and it just works. That could be writing an opus in Word or a quick text message. As a developer there is nothing special we have to do to support this. There are a couple of things to be aware of:-

  1. If the keyboard has special function keys like volume, search, windows etc these do nothing (even if they map to a logical function on the phone).
  2. The Page Up and Page Down keys raise and lower the soft input panel on screen
  3. The keyboard won’t allow you to skip to a section in jump lists (like picking a mail recipient for example)
  4. Although it paired successfully my Symbol CS3070 Barcode Scanner doesn’t actually do anything (When in HID mode it should work as a Bluetooth Keyboard and put the barcode value directly into the keyboard buffer).

There are some interesting subtle visual changes in GDR2. The circular right-arrow button at the bottom of the start screen which provides an alternative to swiping to get to the programs list has been replaced with a more “Big Windows” all apps link

All Apps GDR2

Clear signs of the “oneness” of Windows which will follow!

Categories
Windows Phone

Background GPS in a Windows Phone 8.1 Windows Runtime App

In Silverlight 8.0 there was a capability to run an application for a period of time after the user switched away to perform continuous GPS tracking for up to a few hours. With the switch to the Windows Runtime there was no direct equivalent of this. I discovered however that because there are differences with what you are allowed to do on Windows Phone versus Windows Store apps with the DeviceUseTrigger you can do something similar.

The GPS device itself doesn’t qualify for use with the trigger but you can use another sensor on the device. Since all Windows Phone devices have an Accelerometer you can use this. The documentation states that you must poll the sensor at least every 5 seconds otherwise it will kill your background process. Since GPS commonly updates once per second you are given the choice of polling with a 1-5 second interval depending on what you need. With a bit of logic you could extend this but you’d still be polling the accelerometer at least once every 5 seconds.

The GPS adaptation is simply to recreate a DeviceUseTrigger based background task – using the official code sample as a base. Then we add a Geolocator and get the position on each call of the handler which is called for each reading. In the attached sample we simply capture the position every 5 seconds and update the application tile. So you’ll need to run the app and pin it to the start page to see it at work.

In order to show the minimal code to demonstrate the technique I’ve not added any decent error handling or analytics so don’t just paste this code into a real project and use it as-is.

Sample: BackgroundGps.WinRT

Categories
Windows Phone Windows Store

WinRT Background Task Processes

I’ve been working on a Windows Phone 8.1 project which has several background tasks. One of these uses the device’s sensors – using a DeviceUseTrigger. This is different to how a regular periodic task works because the task implementation creates a deferral and keeps running handling the event generated by the sensor device until it is explicitly cancelled. The task is created normally with a class implementing IBackgroundTask and runs under the context of BackgroundTaskHost.exe. Because I wanted to share some data with the other tasks as a when they run I was interested if these other IBackgroundTask implementations were also hosted in the same process. If so this means that any static instances would be shared between them. Since I couldn’t find the answer I did some testing with some additional debugging and discovered that no, they each run in a separate process.

This lead me to explore how to share data between them. There are no built in IPC classes in the Windows Runtime like MessageQueues or similar so really the only options are the LocalSettings for individual setting values and files placed in the LocalFolder for any other data. The added complication here is that you have to handle the situation where both processes may try to read/write the file at the same time. Luckily you can use a named Mutex to enforce exclusive access to the file and have the other process wait on the Mutex.

Categories
Windows Phone

Nokia CR-201 Car Charger with Lumia 930 Review

I recently got a Lumia 930 and was looking for a simple car holder/charger for it. I saw the CR-201 (which is updated from the CR-200 and advertised as compatible with the 930) and thought it would be perfect because:-

1) It has wireless charging so just pop the phone in, no fiddling with USB cables

2) It looks nice

However it doesn’t really fit the 930 and so this leads to a couple of issues – The clamp mechanism grabs the camera button, the sticky cable ties don’t stick to any material other than the plastic film they ship with and the wireless charger doesn’t deliver a charge capable of supporting charging while using the holder. No doubt this latter issue is also due to the size/positioning just not being right. Sadly it’s only after you discover these issues yourself you then find other reviewers online have encountered the same problems. So it’s going back and I’m looking for an alternative.

Categories
Windows Phone

ProgressRing for Windows Phone updated

Last month I posted the latest “charming” helper for Windows development which is a Windows Phone (8.0 or Silverlight 8.1) ProgressRing with the same appearance as its big Windows counterpart.

Today I’ve just pushed an update to NuGet which improves the flexibility of the control by allowing you to override the Foreground colour of the rotating dots. The default is still to use the phone’s accent colour so this is what you’ll see if you don’t specify the Foreground brush explicitly. Details here:-

http://www.nuget.org/packages/InTheHand.UI.Xaml.Controls.ProgressRing/

Categories
Windows Phone

Data Settings for Nokia Lumia 930 O2 UK (Pay Monthly)

When I first setup this phone and swapped my account over to a new nano-SIM I received a message from O2 that my data and picture messaging settings couldn’t be automatically setup (don’t you just love progress). I had to get the manual settings and now the phone is working as expected. However I thought I’d post them here because they are different to ones I’ve seen posted before and the instructions sent by O2 actually are for older versions of Windows Phone and the names of some items have changed. So here goes…

Tap Settings > mobile + SIM

Tap SIM Settings

Set “Manual Internet APN” to On

Tap “add Internet APN” (or “edit Internet APN” if you tried already). Set the following fields:-

APN = “mobile.o2.co.uk”

Username – “o2web”

Password = “password”

Authentication type = PAP

Proxy server (URL) – leave blank

Proxy port – leave blank

IP type = IPv4

Tap the Save button

For MMS tap the “add MMS APN” or “edit MMS APN” button

APN = “wap.o2.co.uk”

Username = “o2wap”

Password = “password”

Authentication type = PAP

WAP gateway (URL) = “82.132.254.1”

WAP gateway port = 8080

MMSC (URL) = “http://mmsc.mms.o2.co.uk&#8221;

MMSC port = 8002

Maximum MMS size – leave blank

IP type = IPv4

Tap the save button

You should now have working mobile data on your shiny new 930…