One of the most exciting pronouncements at the 2014 BUILD conference was Microsoft’s introduction of “universal apps,” which run on PCs, tablets, and phones. According to Microsoft, universal apps will one day run on Xboxes, too. The universal app represents the first step in a convergence that Microsoft has been seeking for a long time – a convergence of platforms and APIs that allows you to write an application one time and have it run on a variety of Windows devices and form factors.
From a consumer standpoint, a universal app is one that has a single app identity across all devices. Imagine that you buy it once (assuming it’s not free) from the Windows Store, and then download it to your Windows tablet and your Windows phone. Once there, the app offers an optimized experience for each form factor, shares data across devices through the cloud, supports in-app purchases, and more. A consumer could care less whether the same binary is being installed on each device; all he or she knows is that the same app works on a PC, a tablet, or a phone.
From a developer’s perspective, a universal app is not what you might think. It’s not a single binary that runs on multiple platforms. Rather, it takes the form of a Visual Studio solution containing multiple projects: one project for each targeted platform, plus a project containing code and resources shared between platforms. Because Windows Phone 8.1 implements the vast majority of the WinRT APIs that Windows 8.1 implements, a LOT of code can be shared between a Windows project and a Windows Phone project. Most of the platform-specific code you write is UI-related, which, as a developer, I’m perfectly fine with because a UI that looks great on a 30” monitor must be tweaked to look equally great on a 5” phone, and vice versa. Even there, Microsoft has done a lot of work to bridge the gap. For example, Windows Phone 8.1 includes the same Hub control featured in Windows 8.1, meaning you can use similar markup on both platforms to produce a UI tailored to each form factor.
You can download the RC release of Visual Studio 2013 Update 2 and see first-hand what’s involved in building a universal app. I did, and to help developers get acquainted with universal apps, I built a XAML and C# version of the Contoso Cookbook app that I originally wrote for Microsoft to help introduce developers to WinRT and Windows Store apps. The screen shot below shows Contoso Cookbook running side by side on a Windows tablet and a Windows phone. What’s remarkable is how little platform-specific code I had to write, and how similar the XAML markup is for both platforms.
You can download a zip file containing the Visual Studio solution for Contoso Cookbook. Or you can follow along as I highlight some of the more interesting aspects of the development process. Either way, I hope you come away excited about universal apps and the prospects that they hold for the future of Windows development. The future is now, and the future has “universal apps” written all over it.
Getting Started (and Learning to Share)
The first step in implementing Contoso Cookbook as a universal app was to use Visual Studio 2013 Update 2’s New Project command to create a solution. From the list of project types available, I selected “Hub App (Universal Apps)” to create basic 3-page navigation projects anchored by Hub controls:
The result was a solution containing three projects: a Windows 8.1 project named ContosoCookbookUniversal.Windows, a Windows Phone 8.1 project named ContosoCookbookUniversal.WindowsPhone, and a third project named ContosoCookbookUniversal.Shared. Here’s how it looked in Solution Explorer after I added a few more files to the Windows and Windows Phone projects representing flyouts and pages that are specific to each platform:
The Shared project doesn’t target any specific platform, but instead contains resources that are shared between the other two projects via shared (linked) files. In an excellent blog post, my friend and colleague Laurent Bugnion documented some of the ins and outs of working with the Shared project. It can include source code files, image assets, and other files that are common to the other projects. Source code files placed in the Shared project must be able to compile in the other projects – in this case, they must be able to compile in a Windows 8.1 project and a Windows Phone 8.1 project. You can’t add references in the Shared project, but you can add references in the other projects and use those references in the Shared project. Those references can refer to platform-specific assemblies, portable class libraries (PCLs), and even Windows Runtime components. What’s really cool is that if you add references to platform-specific assemblies to the Windows project and the Windows Phone project and the assemblies expose matching APIs, you can call those APIs from source code files in the Shared project.
You can even use #if directives to include platform-specific code in a shared file. In the case of Contoso Cookbook, I needed to add some Windows-specific code to App.xaml.cs to add commands to the system’s Settings pane – something that doesn’t exist in the Windows Phone operating system. So in App.xaml.cs, I added the following conditional using directive:
#if WINDOWS_APP using Windows.UI.ApplicationSettings; #endif
And then, in the OnLaunched override, I added this:
#if WINDOWS_APP // Add commands to the settings pane SettingsPane.GetForCurrentView().CommandsRequested += (s, args) => { // Add an About command to the settings pane var about = new SettingsCommand("about", "About", (handler) => new AboutSettingsFlyout().Show()); args.Request.ApplicationCommands.Add(about); // Add a Preferences command to the settings pane var preferences = new SettingsCommand("preferences", "Preferences", (handler) => new PreferencesSettingsFlyout().Show()); args.Request.ApplicationCommands.Add(preferences); }; #endif
The result was that the code compiled just fine and executed as expected in the Windows app, but effectively doesn’t exist in the Windows Phone app. You can prove it by running the Windows version of Contoso Cookbook, selecting the Settings charm, and verifying that the Settings flyout contains the About and Preferences commands registered in App.xaml.cs:
I added other files to the Shared project so they could be used in the other projects. For example, I added CS and JSON files to the DataModel folder in the Shared project to represent the data source shared by the Windows app and the Windows Phone app, and I added CS files to the Common folder representing value converters and helper components used in both projects. I even added an Images folder containing images used by both apps. Here’s what the Shared project looked like at the completion of the project:
Again, thanks to file linking, you can use anything in the Shared project from the other projects as if it were part of those projects. This provides a common base to build from, and to the extent that you can build what each project needs into the Shared project, you can minimize the amount of platform-specific code and resources required.
Building the UIs
Most of the UI work takes place in the platform-specific projects, allowing you to craft UIs that look great on PC, tablets, and phones alike, but that share common data, resources, components, and even view-models.
Even though the UI for the Windows version of Contoso Cookbook is defined separately from the UI for the Windows Phone version, they have a lot in common that reduced the amount of work required to build them. Each project, for example, contains a start page named HubPage.xaml that uses a Hub control to present content to the user. I used different data templates to fine-tune the UIs for each platform, but the basic structure of the XAML was the same in both projects.
Another UI component ported from Windows 8.1 to Windows Phone 8.1 is the CommandBar class. To implement command bars in both projects, I simply copied the following XAML from ItemPage.xaml in the Windows project to ItemPage.xaml in the Windows Phone project:
<Page.BottomAppBar> <CommandBar> <AppBarButton Icon="ReShare" Label="Share" Click="OnShareButtonClicked" /> </CommandBar> </Page.BottomAppBar>
The click handler calls DataTransferManager.ShowShareUI to display the system’s Sharing pane. (In Windows, you can show the Sharing pane programmatically, or you can rely on the user to show it by tapping the Share charm in the charms bar. There is no charms bar in Windows Phone, so if you wish to share content, you must present the system’s Sharing page programmatically.) Why did I use Click events rather than commanding? Because I couldn’t get commanding on AppBarButtons to work reliably. I assume this is a consequence of the fact that we’re working with tools and platforms that aren’t quite finished yet, and that commanding will work as expected in the final releases.
Both projects use DataTransferManager.DataRequested events to share recipe images and text from the items page. The code to share content is identical on both platforms, so after registering a handler for DataRequested in each project’s ItemPage.xaml.cs, I factored the sharing code out into a static method in the ShareManager class I added to the Shared project, and called that method from each project’s DataRequested event handler. Here’s the relevant code in ShareManager:
public static void ShareRecipe(DataRequest request, RecipeDataItem item) { request.Data.Properties.Title = item.Title; request.Data.Properties.Description = "Recipe ingredients and directions"; // Share recipe text var recipe = "rnINGREDIENTSrn"; recipe += String.Join("rn", item.Ingredients); recipe += ("rnrnDIRECTIONSrn" + item.Directions); request.Data.SetText(recipe); // Share recipe image var reference = RandomAccessStreamReference.CreateFromUri(new Uri(item.ImagePath)); request.Data.Properties.Thumbnail = reference; request.Data.SetBitmap(reference); }
In cases where UI capabilities varied significantly between platforms, I wrote platform-specific code. For example, as noted earlier, since Windows Phone doesn’t have a charms bar, I used #if to include Windows-specific code in the shared App.xaml.cs file to hook into the charms bar. Along those same lines, I added settings flyouts based on Windows’ SettingsFlyout class to the Windows project in files named AboutSettingsFlyout.xaml and PreferencesSettingsFlyout.xaml. Since SettingsFlyout wasn’t ported to the Jupiter (XAML) run-time in Windows Phone 8.1, I added a settings page named SettingsPage.xaml to the Windows Phone project. The screen shot below shows the Preferences flyout in the Windows app and the Settings page in the Windows Phone app side by side:
In each case, the user is presented with a UI that allows him or her to choose to load data locally from in-package resources or remotely from Azure. The code that loads the data and parses the JSON is found in the shared RecipeDataSource class and works identically on both platforms. (Fortunately, the Windows.Data.Json and Windows.Web.Http namespaces are present in WinRT on the phone and in Windows, so the code just works in both places.) And in each case, I built the settings UI around the ToggleSwitch control that’s present on both platforms. Same concept, different implementation, and a perfect example of how platform-specific projects retain the ability to use platform-specific APIs and controls without impacting the other projects.
I didn’t include search functionality in the apps even though it was present in the original Contoso Cookbook. I will probably add it later, but the reason I chose not to for now is that while Windows has a SearchBox control, Windows Phone does not. That means I’ll need to build my own search UI for the phone – not a big deal, really, since I can easily put the search logic in a component that’s shared by both projects.
The Bottom Line
Most of the code that drives the Windows app and the Windows Phone app is shared, and while the UIs are separate, they’re similar enough that building both was less work than building two UIs from scratch. If I had built a Windows Phone version of Contoso Cookbook for Windows Phone 7 or 8, it would have been a LOT more work since Windows Phone 7 contained no WinRT APIs and Windows Phone 8 contained only a small subset.
If you’re interested, I’ll be delivering a session on universal apps at the Software Design & Development conference in London next month. It should be a fun time for all as we delve into what universal apps are and how they’re structured. I’ll have plenty of samples to share as we party on universal apps and learns the ins and outs of writing apps that target separate but similar run-times.
Microsoft has talked a lot about “convergence” in recent months, and now we see evidence of what it means: one API – the WinRT API – for multiple platforms, and a high degree of fidelity between UI elements for each platform that doesn’t preclude developers from using platform-specific elements to present the best possible experience on every device. This is the future of Windows development. And for many of us, it couldn’t have come a moment too soon.
Secure from design through deployment.
Our business is built on ensuring customer environments are secure from design through deployment and to provide solutions which are realistically implementable. We provide managed Information Security (InfoSec) and compliance options across the entire computing stack, from connectivity to applications, with stringent physical and logical security controls.
Define your objectives.
We partner with your team to define the right security profile for your business needs.
Build your foundation.
Together we develop comprehensive best practices encompassing all aspects of security: people, process and technology.
Execute your roadmap.
We collaborate to build and evolve an information security program that bolsters your security profile.
More than technology
All Atmosera customers benefit from processes, policies, training and 24x7x365 technical resources.
Our customers have the peace of mind of knowing an industry expert has performed a thorough risk assessment, identified a remediation plan and provided ongoing audit support to ensure customers stay secure.
Best of all, we understands this level of service is — and will continue to be — required year after year.
We always implement networks which
deliver better security and usability.
All our deployments take into consideration the end-to-end solution and we secure all aspects of the network and connectivity.
- Defense in Depth – Our approach offers a flexible and customizable set of capabilities based on enterprise-grade standards for performance, availability, and response.
- WANs, MANs, LANs, and VPNs – We provide comprehensive networking and high-speed connectivity options from Wide Area Networks (WAN), Metropolitan Area Networks (MAN) and Local Area Networks (LAN), as well as managed Virtual Private Networks (VPNs) and firewalls.
- Stay current – We can be counted on to deliver proactive testing and the most secure network protocols.
- Reduce vulnerabilities – We help your team leverage advanced security features coupled with relentless vigilance from trained experts.