Thursday, April 10, 2014

Universal Apps: What Are They And Can I Use Them With Xamarin?

At Build this year the new Universal App type was announced that allows you to write apps on for both the Windows Store and Windows Phone 8.1 platforms with one code base.  There were also hints that this would be supported in Xamarin as well.  Exactly how these work was a little unclear to me so I downloaded the Visual Studio 2013 update 2 RC and did some experimentation, at least what is possible in the release candidate.  The Visual Studio 2013 Update 2 RC can be found here:

I opened up the new project window and with a little searching around this is what I found:

There are four new project types:

  • Blank App (Universal App) - Very simple solution to create two projects (Windows Store and Windows Phone 8.1) and one shared universal project with a nifty new icon
  • Hub App (Universal App) - Slightly more complex than the Blank app, it still creates a Windows Store and Windows Phone 8.1 projects both using the same shared project
  • Class Library (Portable for Universal Apps) - Creates a project to create a Portable Class Library (DLL) in the profile that supports Windows Store 8.1 and Windows Phone 8.1 applications.  Currently there are no profiles that support Windows Phone 8.1 and Xamarin so I was not able to make one of these that also supports Xamarin but I suspect this will be updated soon enough.  This project type is intended to create libraries that can be shared outside the solution.
  • Windows Runtime Component (Portable for Universal App) - Similar to the Class Library type except compiles into a winmd file instead of a dll.

Blank App (Universal App) - This creates a new universal app solution with three projects, One for a Windows Phone 8.1 UI, one with a Windows Store Application and one shared universal application which would seem to be where the interesting bits are.

The new shared app type just shows up with an xaml file and is referenced by both the Windows Store application and the Windows Phone 8.1 application.  This is a project type unlike what you may be used to, in fact it appears to be only a repository for shared code that can be used by other projects in the solution.  Here are some things that are of interest:

  • If you right click on the shared universal project and select properties all you can change is the root namespace.  That's it.
  • When compiled no DLL is generated for this project, all code in it is compiled directly into the Windows Store and Windows Phone 8.1 applications.  These projects cannot be independently be shared or used outside of the projects that directly reference them in a solution.
  • You cannot compile only the Shared project on the build menu, it cannot be built independently.  This makes sense give that it has no output and is compiled directly into a referencing project.
  • As of the time of the writing there is no references nor ability to add references to the shared project through the Visual Studio UI.  What is available to you within code of these projects is the subset of the .NET framework for this project and that's it.  That means no referencing Autofac or any third party library in code through the Visual Studio UI. 
  • EDIT TO PREVIOUS VERSION - The shared project *WILL* pickup references in the projects that reference them.  You have to select the proper project in the upper left dropdown when editing a file in the shared project and it will pickup the proper references.

Here is a screenshot of the project selection dropdown where you can select the right platform specific project and get the proper references and conditional compilation symbols:

I wasn't satisfied with the last point as it would be extremely limiting so I decided to do some experimentation.  I went out to Nuget and added the latest stable version of Windows Azure Mobile Services to the Windows Store and Windows Phone 8.1 projects.  I then opened up the Windows Store project file in Notepad and copied the following code to the shared project file from the Windows Store project file:

  <Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\..

\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
  <Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
    <Error Condition="!Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This 

project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more 

information, see" HelpKeyword="BCLBUILD2001" />
    <Error Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build 

restored NuGet packages. Build the project again to include these packages in the build. For more information, see" HelpKeyword="BCLBUILD2002" />

When I refreshed the shared project I still had no references section visible in the project on the Visual Studio UI.  However, I then created a new class in the Shared project with the following code:

using Microsoft.WindowsAzure.MobileServices;

namespace App1
    class ReferenceTest
        private MobileServiceClient Test1()
            return new MobileServiceClient("");

Granted this code is rather useless but Visual Studio now recognized that Microsoft.WindowsAzure.MobileServices is valid in the shared project.  I was able to compile both projects using the shared project just fine.  So there may not be support in the Visual Studio UI for this at the present time but it does appear possible to reference other assemblies in your shared project.  Of course when I removed the Windows Azure Mobile Services reference from my Windows Phone 8.1 project, it no longer compiled though the Windows Store project continued to compile so any references added to the shared project also need to be added to any project that reference it, which makes perfect sense.

How about Xamarin?  As I stated before I couldn't create a Portable Class Library for Universal Apps that also referenced either Xamarin iOS or Android as there did not seem to be a profile for that combination.  What about the shared project?  I went ahead and added Xamarin iOS and a Xamarin Android UI projects to the solution.  I then went to the references section of the Android project and tried to add a reference to App1.Shared like there was in the Windows Store and Windows Phone 8.1 projects.  No luck, that wasn't an option when looking at the solution nor could I browse out to a DLL because one does not exist.

I did, however, find the following blog post that states how to modify the project file:

I took the advice and added the following code to my Android project file in Notepad (As noted in the blog, be careful about the path being correct or your project will not load):

<Import Project="..\App1\App1.Shared\App1.Shared.projitems" Label="Shared" />

When I then reloaded the Android project as the blog post indicated I suddenly has a reference to the shared universal app project.

When I tried to compile I couldn't for two reasons.  First the default Blank App added a Xaml file to the shared app, App.xaml. Currently xaml isn't going to be usable by the Android or iOS projects and so can't exist in App1.Shared.  I moved this to the individual Windows Store and Windows Phone 8.1 applications (I could also have used pre-compilation directives so it wouldn't be visible to the Android project to the same effect). 

The second reason is because the shared project uses the Windows Azure Mobile Services component and my Android project does not reference it.  I added this and the problem was resolved (Note: sometimes when getting the Windows Azure Mobile Services package for Xamarin from Nuget it drags along some extra system DLLs that I have to delete: System.IO, System.Runtime and System.Threading.Tasks).

With these issues resolved I am able to use the shared project in Xamarin Android.  By following the same steps I am able to do it with the Xamarin iOS project as well.

In conclusion, what have I learned about the present state of Universal Apps and Xamarin?

  • Universal PCLs and winmd projects won't work with Xamarin at the present time because there is no profile that supports Windows Phone 8.1 and Xamain project types.  I expect that to be resolved.
  • Creating a Universal Blank App or Hub app creates a shared project type
    • The shared project cannot be created directly through the Visual Studio UI and instead must be created through one of those two project types
    • Code in the shared project does not create a DLL or winmd file but instead is compiled directly into the projects that reference the project
    • There is no way through the Visual Studio UI to add a reference to an external dll to a shared universal project but references can still be added by editing the project file directly
    • You do not need references in the shared project because it picks up references form the projects that use it.  When in a code file you can switch between projects to pick up their references and conditional compilation constants
    • All projects that reference the shared universal project must reference and be able to use any code in the shared project or measures such as pre-compilation directives must be used
    • Xamarin iOS and Android UI projects can use the shared project but only if their project files are edited directly as there is not currently any way to do it through the Visual Studio UI

In general the shared universal projects would seem to be a new alternative to the old method of simple linking a shared code file between two or more different projects.  As is common with that method platform specific differences can be handled via pre-compilation directives.  Any sharing of the UX may work on projects that use xaml but of course such code is not currently workable in Xamarin Android and Xamain iOS and would have to be hidden from those project types.

UPDATE: If you want to create a PCL today that targets Windows Phone 8.1 and Xamarin Android and/or Xamarin iOS @danrigby has a great blog post that explains how to do it until an update is released:

Friday, April 4, 2014

The .NET Foundation and Xamarin

Miguel put this post on his blog discussing the joint announcement of The .NET Foundation:

The .NET Foundation is an attempt to create cross platform language syntax for the features of the platforms where they operate similarly.  This is similar to what Microsoft has done with Azure's Mobile Service's Identity.  With Mobile Services Identity Microsoft realized that as a developer I don't care if I'm trying to authenticate against a Live account, Google, Twitter or Facebook.  All I care about is what service the user is authenticated with and the token returned.  The differences in syntax were not of interest to me, in fact as a developer they created a harmful knowledge barrier.  So Microsoft takes care of the differences in syntax and I just write against one unified syntax.

The .NET Foundation is bringing us more of the same for mobile platforms.  Do I care about the syntactical differences in Geolocation or the contact systems?  No probably not, so we have Xamarin Mobile.   Do we care about differences in how mail is sent out?  No probably not, so we have MailKit and MimeKit.  Ultimately anything that has common functionality between systems can be abstracted out behind a common language library to give common syntax.  This is big, huge in fact, for cross platform development.  The more knowledge barriers that can be removed between platforms, the less expensive and more maintainable native cross platforms solutions can be.

This got me thinking, what can't easily be abstracted out across platforms to a common syntax for a truly engaging and flexible native applications?  Two things quickly come to mind:

- The user experience.  Applications running on iOS that look like Android applications or Windows Phone apps do not create an engaging user experience and vice-versa.  The users on those platforms expect things to look a act in certain ways.  This isn't just the look and feel of the controls, it may be the general design of the screens themselves and the flow between screens, how menus operate, etc.

- Platform specific features and flow.  It's important to know that you can pass reference types between controllers on iOS but not between activities in Android.  Sometimes you need access to those properties, methods and events that exist on one platform and not the other.  It is similarly important to understand the lifecycle differences between the platforms, the fact that JIT code won't work on iOS, etc.  This type of platform specific knowledge will always be needed to write an application that looks, feels and acts like a native application and performs well on that platform.

If we look at these one at a time what do they mean?  For the user experience what is important is that we can create difference views on each platform with different layouts and a different look and feel.  What isn't as important is the syntactical differences in what the controls are.  Most of the time when I want to display some text I don't care if what I need to create is called a TextView or a UILabel.  I just want some control to display some text.  Similarly when I'm laying out the view I know that I want controls to appear in a certain order and usually be responsive to changes in the size of the UI.  Do I care if I'm using the XCode designer, some controls created and positioned in code or a LinearLayout for that?  Probably not.  So I can envision some sort of common designer with common syntax being created that will have a different look and feel (i.e. the correct native controls being used) when I'm in a Windows Phone project, an Android project or an iOS project.  But that will only take you so far which brings me to platform specific features and flow.

The platforms are different.  Whether it be fragments in Android or the TouchUpOutside event in iOS.  Activities and iOS controllers behave differently.  Those types of behavioral and feature differences will be hard to get away from and still create a native application that behaves and runs well on the individual platforms.  To the extent that they may be able to make a common syntax name for a button that actually creates the correct button on the native platform, that's great.  To the extent that they can use a common layout scheme like XAML that creates the appropriate native specific controls and layout, that's even better.  A single designer that works the same but looks differently on Andoird, iOS, Windows Phone and WinRT, that would be better still.  But at the end of the day we are still likely to need some sort of platform specific extensions to get at the control features and layout capabilities that are unique to one platform or the other.

I don't even know if common control syntax or designer while preserving native look, feel and flow is truly feasible.  Even then, we will likely still be creating multiple versions of the views that look/behave correctly on each platform even if the syntax is mostly the same.  It will be fun and interesting to see how this plays out; what things can have standardized language syntax while still preserving the platform specific look, feel, features and flow and what things can't.  I'd love to see that single UX designer that is emitting the correct native platform code.  Sure I still may be creating platform specific layouts but my tool and syntactic knowledge will be similar; that is, the platform specific knowledge barriers will be lowered. 

We will still need to know about how the individual platforms work, I don't think we will be able to move away from that and make native applications that look, feel and operate like native applications.  The .NET Foundation is clearly moving in the right direction to lower many of those barriers.  In the final analysis this clearly strengthens the value proposition of Xamarin and C#/.NET in cross platform development, which is kind of interesting in that it was one of the original thought processes behind .NET.  It just took us a while (and some people with vision and perseverance) to make it happen.