June 20th, 2014

VB Universal Windows App Part 5: calling into platform-specific APIs from PCL

This is Part 5 of the “VB Universal Windows App” series:

So far we’ve been able to re-use all our code and XAML by placing them in the PCL. Actually, PCLs can only ever contain calls to APIs that are common to the platforms they target. This generally isn’t a problem, because most APIs on Windows also exist on Windows Phone, and vice versa.

Today we’ll explore how to call platform–specific APIs from Common code. In particular, we’ll make it so our common main page can hide the Windows Phone statusbar (with connection quality, battery, clock) – when it’s running on Windows Phone, of course. There’s nothing that needs hiding on Windows.

Inversion of Control

We’ll use a technique known as “Inversion of Control” (IOC). It sounds complicated but is easy in practice. Advanced developers frequently use IOC for unit-testing as well.

 

Step 1: Declare a new interface “IPlatformAbstraction” in App1_Common > App.vb, and a public field of that type.

Public Interface IPlatformAbstraction
    Function SetStatusbarVisibilityAsync(isVisible As Boolean) As Task
End Interface

Public Class App
    Public Shared Platform As IPlatformAbstraction
    ….
End Class

Step 2: Any time you want to play audio from within App1_Common, do so via the platform abstraction layer:

Await App.Platform.SetStatusbarVisibilityAsync(False)

 

Step 3: Now you have to provide two implementations of the interface, one in App1_Windows, and one in App1_Phone. I chose to provide it inside my two App.xaml.vb files. Remember also to assign “App1_Common.App.Platform” inside the OnLaunched method.

NotInheritable Class App
    Inherits Application
    Implements App1_Common.IPlatformAbstraction
 
    Public Async Function SetStatusbarVisibilityAsync(isVisible As Boolean) Implements IPlatformAbstraction.SetStatusbarVisibilityAsync
        ‘ TODO: implement this!
    End Sub
 
    Protected Overrides Sub OnLaunched(e As LaunchActivatedEventArgs)<
        App1_Common.App.Platform = Me
        ….
    End Sub
 
    ….
End Class

 

How to deal with status-bar visibility on Windows Phone

Look at these screenshots. (To test how my app behaves with “software-buttons” I launched either the 720p or 1080p emulators, clicked on >> then Sensors, and turned on software buttons).

ApplicationView.GetForCurrentView().SetDesiredBoundsMode(
                    
ApplicationViewBoundsMode.UseCoreWindow)

The screenshot on the left used ApplicationViewBoundsMode.UseVisible. You can see that it calculated the layout rectangle of my page based only on what’s visible, after you take away the space for software-buttons and status-bar.

The screenshot on the right used ApplicationViewBoundsMode.UseCoreWindow. You can see that it calculated the layout rectangle of my page based on the full screen size, regardless of software-buttons and status-bar.

 

 

The status-bar visibility (at the top) is under the app’s control. The app can show or hide it. Showing and hiding takes about half a second, since it’s accompanied by a nice animation. These are the two methods you can use:

    Await StatusBar.GetForCurrentView().ShowAsync()
   
Await StatusBar.GetForCurrentView().HideAsync()

 

The software-button visibility (at the bottom) is under the user’s control. And most phones come with hardware buttons, not software buttons, so they don’t even show these.

 

Step 4: Implement the SetStatusbarVisibility method of our Platform Abstraction Layer:


   
‘ PHONE IMPLEMENTATION, in App1_Phone > App.xaml.vb
    Public Async Function SetStatusbarVisibilityAsync(isVisible As Boolean) Implements IPlatformAbstraction.SetStatusbarVisibilityAsync
        If isVisible Then
            Await StatusBar.GetForCurrentView().ShowAsync()>br/>         Else
            Await StatusBar.GetForCurrentView().HideAsync()
        End If
   
End Sub

    ‘ WINDOWS VERSION, in App1_Windows > App.xaml.vb
    Public Async Function SetStatusbarVisibilityAsync(isVisible As Boolean) Implements IPlatformAbstraction.SetStatusbarVisibilityAsync
        If False Then Await Task.Delay(0) ‘ dummy to silence the compiler warning
   
End Sub

 

Fire-and-forget async methods

There’s one final tweak I want to mention. It’s inside App1_Common > AdaptiveMainPage.xaml.vb > OnNavigatedTo that I want to call SetStatusbarVisibilityAsync.

But hiding the statusbar has a half-second animation, and I don’t want to delay my OnNavigatedTo method while waiting for it to finish. In effect, I want to just kick off the async method in a fire-and-forget manner.

Here is a nice idiom for fire-and-forget asyncs. It uses an extension method “FireAndForget” which I wrote. It silences the compiler warning (“hey you’re not awaiting this async method”). And it demonstrates to anyone reading my code what I’m trying to do:

    App.Platform.SetStatusbarVisibilityAsync(False).FireAndForget()

And here’s how I implement that FireAndForget extension method:

Module AsyncHelpers
    <Extension> Async Sub FireAndForget(task As Task)
        Try
            Await task
        Catch ex As Exception
            App.SendErrorReport(ex)
        End Try
    End Sub
End
 Module

Actually, in practice, I also often write two additional FireAndForget overloads, to make it easy to use with asynchronous WinRT APIs. They’re implemented exactly the same way:

    <Extension> Async Sub FireAndForget(task As IAsyncAction)
    <
Extension> Async Sub FireAndForget(Of T)(task As IAsyncOperation(Of T))

 

Conclusion

We’ve now created a complete VB Universal app – although under the hood, a universal app is really two separate apps. In this blog series we’ve used two techniques for sharing code between the two apps. We’ve been able to share most of our code, XAML and assets by putting them inside a PortableClassLibrary. And we’ve used Inversion Of Control (IOC) to let the PCL call into platform-specific APIs.

Good luck, as you go out and build your own VB Universal Apps! It’s an open app-store out there, ready for you to make your impact.

And stay tuned for tomorrow’s blog post, with complete source code for the minimal “App1.vb” that we’ve been creating so far, and also complete source code for a fully-fledged universal VB game “Breakout Universal”.

Author

0 comments