The world wide web is one of the most powerful tools available to us. A lot of its power comes from how easily web sites can work with each other to answer questions and solve problems. Wouldn’t it be great if every device contained a web of apps working together rather than just the silos we see today? In this talk we discuss the tools available to developers to build just such a web of apps on Windows 10, including launchers, pickers, app services, and more. Come see how apps get better when they work together.
The video is up now. Come learn all about building a web of apps:
If you’ve been following along on my blog posts or interacting with me on Twitter, you’ll know that I’m fascinated by the idea of building a web of apps on every device. This is especially true on app centric mobile and tablet devices. But the idea also applies to browser-centric desktops because, sometimes, an app is the way to go.
The very first, and possibly the defining characteristic of the web is it’s interconnectedness. The ability for a web site to link to another one seamlessly. The irony is that an app can just as easily link to a web site hundreds (possibly thousands) of miles away. But when it comes to linking to other apps on the SAME device, well, that just happens a lot less often.
Fortunately, custom schemes or custom protocols are a great way for apps to connect to each other on-device. In fact, there’s sizable industry momentum building around the idea of using custom schemes to deep link between apps. There are at least three initiatives that I’m very interested in and have been following closely in this area:
All three have interesting facets of their own but the idea is simple: take an http link (such as http://spotify.com/artist/Beyonce) and provide a way to transform it into a custom scheme link (Spotify://artist/Beyonce).
Custom schemes aren’t new. They’ve been around since at least 1996 when the Internet Explorer team (yes, that Internet Explorer!) first debuted them at Microsoft’s Professional Developer Conference. Other notables at that conference? A keynote by Douglas Adams, a session by Steve Jobs and our very own Andrew Clinick (@andrewclinick) as an attendee. Andrew also happens to be my source for this info! Basically, the idea is that an app signs up for a custom scheme and then other apps can launch it with a URI that uses the custom scheme. The wonderful thing is that custom schemes works on Windows, Android and iOS. Of course the APIs are different on every platform. If you’re interested in how custom schemes work on iOS, start here. Here’s how they work on Android. A detailed walkthrough that shows how to handle custom schemes in a Windows app lives here.
Okay, that’s great. You defined a custom scheme that can be used to deep link into your app. You’ve also decorated your http pages with the right metadata so other apps can find your custom scheme. Pretty soon, you’ll discover a problem that is unique to custom schemes. There is no authoritative way to take ownership of a custom scheme! Say you went with myawesomeapp: and you’ve got apps in the Android, Windows and iOS stores. That does not prevent someone else from coming along and using the same scheme. Unlike the World Wide Web, there is no central authority that polices and mandates that these schemes be unique. You can use strategies like reverse domain naming which is recommended by the Internet Engineering Task Force. But that still doesn’t prevent a malicious app from engaging in this behavior.
So, what ends up happening is that an app attempts to deep link into your app and the user might end up in a place neither you nor the calling app expected. I call this the Evil Twin problem. How do you prevent your friends directing a user to your evil twin instead of you on Windows? Well I’m glad you asked!
First things first, here’s how an app deep links into another app on Windows:
var options = new LauncherOptions(); options.TargetApplicationPackageFamilyName = “24919ArunjeetSingh.Build2014PhotoBlog_5gh9hndrtk5nw”; await Launcher.LaunchUriAsync(new Uri(“com.aruntalkstech.tumbleme:?Oh=Yes”), options);
We add LauncherOptions when calling the LaunchUriAsync API. The new launcher option we are using is called TargetApplicationPackageFamilyName. A Package Family Name is simply an identifier that uniquely identifies a Windows app. The assumption here is that at some point, the owner of the app we want to deep link into (the app that signed up for com.aruntalkstech.tumbleme://) gave us their package family name. Now it is important to note that every Modern windows app has a package family name. The simplest way to obtain the package family name for your app is to call the Windows.ApplicationModel.Package.Current.Id.FamilyName API within the app. This works for Silverlight 8.1 apps, Windows Phone 8.1 apps, Windows 8.x apps and of course Windows 10 apps.
Where does the Package Family Name come from? Lets analyze the one above: 24919ArunjeetSingh.Build2014PhotoBlog_5gh9hndrtk5nw. The part before the underscore is a generated name the Windows developer center gave me when I reserved a name for my app. So this part is unique to my app within the Windows store. It is also what is known as the Package Identity Name. The second part is a hash of the certificate used to sign my app. Remember, your users will either obtain your app from the Windows store or by way of an enterprise deployment. Either way, it will be signed using a certificate issued to you for app signing. So unless you manage to compromise that certificate, you can be sure that another app can’t steal your package family name.
The share contract is the API that drives the share charm (on Windows 8) and share button on Windows. This feature has been around since 2012. Thousands of app in the Windows and Windows Phone app stores share content using the share contract. That’s because the share APIs are a great way to share content with social networks, email, text messaging and any other communication apps a user might have installed on their device. If you’re not familiar with the API, this MSDN article is a good starting point as is my Build talk from last year.
However, one thing that has always bothered me about share is that all the existing Win32, WinForms and Windows Presentation Foundation (WPF) apps can’t share content using these APIs. Well, we set out to remedy that situation last year as we started building out Windows 10. As we were building out the feature, we brought in partners early on who could help us validate our code. The File Explorer team kindly signed up to share files with Modern apps and that gave us a lot of early test data and helped us iron out bugs in the feature. If you’d like to try out the feature on Windows 10, just go into the file explorer and select a file, open the Share ribbon on top and click the Share button.
Important Note: When sharing from a Win32 app, two requirements apply:
The source window (from where you call ShowShareUI) must have focus and be visible
The ShowShareUI must be called from the top-level window. It can’t be one of the children of the top-level window
Now that we’re coming up on Build I wanted to talk about this feature and walk through how a Win32, WinForms or WPF app can share content on Windows 10. If you’re the kind of person who wants to jump straight into code, well, it all lives here: https://github.com/arunjeetsingh/Build2015/tree/master/Win32ShareSourceSamples. Feel free to clone, log bugs and submit pull requests if you have fixes for me. From this point on, I’m going to assume you’re looking at the code and can follow along. Lets start by taking a look at the WPF project called WpfShareSource. This project shows how a WPF app can share text, URI or a file using the share API. Of course, you can also share any of the other formats if you want to but these happen to be the most common ones so they’re a good starting point.
Figure 1: New references in WpfShareSource.csproj
The WpfShareSource.csproj file contains a set of references that you might not find in a typical WPF project. To be precise, there are references to three new things:
System.Runtime.dll gives us access to some runtime related features used by the Windows 10 (and 8) API surface. This includes things like iterators and async operations.
System.Runtime.WindowsRuntime gives us access to some nice .NET friendly wrappers for APIs like RoGetActivationFactory.
The Windows.winmd reference gives us access to the complete Windows 10 API surface
Note that you might have to update the paths depending upon how you’re set up. It’s something I’m hoping to remedy with a future commit.
Okay, so now we have a WPF project that can consume Windows 10 APIs. Nothing new there, you could do this with Windows 8 as well. The really interesting bits live in a file called DataTransferManagerHelper.cs. The first thing worth noting is the IDataTransferManagerInterOp interface defined at the bottom of the file. We need to bring this interface in because it is a COM interface that isn’t already available in WPF or WinRT. This interface really is the thing that drives a Win32 app’s interaction with the share infrastructure. IDataTransferManagerInterOp has two methods:
GetForWindow – Those method lets a Win32 app get a DataTransferManager attached to a given window handle (usually the app’s own main window). Note that this is the same DataTransferManager that Modern apps use. But while Modern apps use the GetForCurrentView static method to get an instance of DataTransferManager, Win32 apps must use IDataTransferManager.GetForWindow.
ShowShareUIForWindow – This is the method a Win32 app must call to pop open the share picker. All it needs is a window handle. As with Modern apps, the request to retrieve data comes in via the OnDataRequested event hanging off of the DataTransferManager class.
Figure 3: The DataTransferManagerHelper class
The DataTransferHelper class is a nice wrapper around IDataTransferManagerInterOp. The constructor of this class accepts a window handle. It gets an activation factory for DataTransferManager and casts it to an IDataTransferManagerInterop. Then we use the IDataTransferInterOp instance to get a hold of a DataTransferManager instance using the GetForWindow method. We hold on to the DataTransferManager instance as a property on the DataTransferManagerHelper. We also hold on to the instance of IDataTransferInterOp as a member variable. Finally, DataTransferManagerHelper.ShowShareUI simply calls ShowShareUIForWindow on the IDataTransferManagerInterOp instance it’s holding. Okay, now that we have all the pieces in place, lets take a quick look at MainPage.xaml.cs where all the action happens. On MainPage, we’ve got a button each to share a piece of text, a weblink and a file. The click handlers of these buttons simply ensure that a DataTransferManager is set up, put the app into the right sharing mode (text, weblink or file) and kick off share by calling the DataTransferManager.ShowShareUI method.
The EnsureDataTransferManager method creates a new DataTransferHelper if one doesn’t already exist and then sets up a handler for the DataTransferManager.DataRequested event. The DataRequested handler is the code that the share picker calls once it is ready to pull the data it needs for sharing. That’s it! That’s how a WPF app can share content with Modern share targets on a Windows 10 device. The solution also has projects showing how a WinForms .NET app can share content as well as a simple Win32 app that shares text. Happy hacking!
I wanted to really quickly make a note that the first commit of my Build 2015 demo is now up on https://github.com/arunjeetsingh/Build2015. If you’ve been following me on Twitter (@aruntalkstech) you might know that I plan to build my Build demo in my GitHub repository. The code in there should build with the latest Windows 10 preview tools but not all of it runs flawlessly on 10041 or 10049. So while you can play around with it be wary of not implemented exceptions and other places you’ll fall off a cliff because we’re not done yet. Still, great way to explore what’s coming.
Here’s a quick back of the envelope map of the world showing what’s interesting in there:
Contoso Shop: This project is a shopping app that lets you look at expensive Roombas and buy one. Eventually the Roombas will probably get replaced with something more generic because the lawyers won’t let me give iRobot free advertising.
If you haven’t heard the news, well, let me be the first one to let you know. The tools for building apps for Windows 10 are here: http://dev.windows.com/en-US/windows-10-developer-preview-tools. Sure, it’s still Visual Studio and a Windows SDK but the BIG difference this time is that not only can you build for Windows and Windows Phone, you can also build for potentially any platform that runs Windows out there. That includes Xbox, Hololens, Raspberry Pi, the Surface Hub, tablets, laptops, desktops, phones. And those are just the ones I know about!
The ambition of the Windows 10 release and the scope of this SDK is hard to overstate. Over the past year, we’ve been busy building a set of tools to connect apps on Windows in my little corner of the world. You see, my team work on a bunch of APIs that apps can use to talk to each other. These APIs give apps the ability to share data with each other using the share contract, launch each other using custom URI schemes and file associations, share files with each other using the file picker APIs. We also work on humble but important APIs such as the clipboard APIs. Basically, any time an app needs to talk to one of the other apps on a device, we come into play.
With Windows 10, our challenge was to extend these APIs all of the devices Windows is now available on. Now, not all the APIs work exactly the same everywhere. There’s no sense in making the share picker on the phone fly out from the right and cover only part of a small screen for example. The clipboard on an Internet of Things (IoT) device such as the Raspberry Pi will have **some** differences compared to the one on a full-blown desktop machine. Nevertheless, we wanted to make the majority of these APIs universally available so that apps on all these devices could talk to each other.
Our vision of app to app APIs (app to app is what we call ourselves and we’re still looking for a nicer name :D) has always been one of a web of apps. There is no reason apps have to be islands. Now that does not mean app isolation isn’t important. It is VERY important. In fact, the lack of true app isolation on most desktop class operating systems frequently means that a user’s experience can be held hostage by one or a handful of rogue apps (virii, malware et al). However, that does not imply that every app must be an island unaware of other apps on the device. The user forever doomed to shuttling in and out of the start (or home) screen trying to accomplish the simplest tasks.
When apps talk to each other beautiful things happen. You install one app and it enriches your experience in other apps you might already have. We’ve all seen this happen, but it is still something of a dark art. Our goal is to make app to app communication easier, less of a dark art and make your device as useful as your browser. You should never, ever have to choose an app before you choose what to do. We’re not quite there yet, but I think you’ll agree it is a noble goal.
Thanks for reading this far. For the next few posts, I will be talking about enhancements and new app to app features we have built for Windows 10. Please use comments or my twitter handle @aruntalkstech to reach out. The code will always be at http://www.github.com/arunjeetsingh. Happy hacking!