Some of you read that title and thought: “Of course it crashes on desktop! You can’t send text messages on desktop!”. However, as you’ll notice here, the Windows.ApplicationModel.Chat.ChatMessageManager is a universal API. That means a universal app can use this API without having to add any mobile specific extensions. This is great, because it allows you to build a single app that can light up text message features on Windows 10 versions where sending text messages is supported while still making all the other features available elsewhere.
the ChatMessageManager.ShowComposeSmsMessageAsync API crashes the app on desktop. Even worse, it isn’t the kind of crash that can be handled by an app. Anyway, having to swallow an exception in order to find out whether sending texts is available would be a pretty crappy way to handle this. What if I don’t want to draw the Send Text Message button unless text messaging is available. Well, worry not, for ChatMessageManager.GetTransportsAsync is riding to the rescue!
The GetTransportsAsync API simply returns a list of chat messaging transports available on a device. What this means that at the moment this API will return an empty set on desktop and a set of 1 or more transports on mobile. So, it should be straightforward to write code to check if a transport is available before calling ShowComposeSmsMessageAsync (or drawing the button). That’s exactly what the sample at https://github.com/arunjeetsingh/SampleCode/tree/master/ComposeTestMessage does. Note that your app will have to have the “chat” capability to use the ChatMessageManager.GetTransportsAsync API. The sample app does this by declaring the capability in it’s package.appxmanifest. Thanks to Maurizio Manca for pointing that out in the comments.
As always, feel free to reuse the code in there in your app and send in a pull request if you find a bug.
I just put up a new sample at https://github.com/arunjeetsingh/SampleCode/tree/master/Win32AppServiceClient. My apologies to all the folks who have been waiting for this sample. I know I promised I’d put up this sample during my Build talk. Well, here it is now. Better late than never right! Who uses this feature? Well, the brand new Outlook 2016 desktop app uses it to talk to Cortana so you’re in good company. Before I dive any deeper into the sample I do want to point out a couple of important limitations of app services when they are called from a Win32 process:
The calling app must be running as the currently logged on user.
When the calling app is a Win32 app the app service background task can not run longer than 30 seconds.
The sample demonstrates a Windows Presentation Foundation (WPF) app calling a universal app service. App services are a new feature of universal Windows 10 apps that allow an app to provide services to other apps. These services can be accessed by other apps as well as Win32 apps such as WPF or WinForms apps.
This sample demonstrates how a WPF app can call into an app service. To run the sample you will need Visual Studio 2015 and the Windows SDK. Both of these can be found at http://developer.windows.com.
With Visual Studio, open the solution Win32AppServiceClient.sln. There are three projects in this solution:
RandomNumberService – This project is a Windows Runtime component. It contains the code for the background task that implements the app service we use for the sample. RandomNumberGeneratorTask.cs contains the background task class. The background tasks’ main entrypoint is the Run method. In this method, the RandomNumberGeneratorTask sets itself up with a deferral so it can stay running and provide the app service. It also uses the incoming AppServiceTriggerDetails to attach an event handler to the AppServiceTriggerDetails.RequestReceived event. This enables the RandomNumberGeneratprTask to respond to requests from the app service client. The OnRequestReceived handler simply parses the input for minimum and maximum integer values. It then generates a random number between those values and returns it.
AppServicesProvider – AppServicesProvider is the universal Windows app that contains RandomNumberService. The AppServicesProvider project contains a reference to RandomNumberService. The Package.appxmanifest file in AppServicesProvider also contains a windows.appService extension. This is how the AppServicesProvider app exposes the RandomNumberService to other apps. In the Package.appxmanifest’s uap:Extension element the EntryPoint attribute represents the type name of the background task providing the app service. The Name attribute in the uap:AppService element represents the name of the app service.
Win32AppServiceClient – The Win32AppServicesClient is a WPF application. The project file of this WPF application (Win32AppServiceClient.csproj) has been modified to include references to the universal Windows 10 APIs. This enables us to use the Windows.ApplicationModel.AppService.AppServiceConnection class that lets an app connect to an app service. The MainWindow.xaml page of Win32AppServiceClient does exactly that. It presents the user the option to provide minimum and maximum integer values. The Click handler of the Generate Random Number button then calls the random number service exposed by AppServicesProvider with these values. The result is then displayed on screen.
Feel free to submit pull requests on this README.md or the code if you think it could use improvement. Happy hacking!
If you’ve been following along on the new app to app communication work we’ve done with Windows 10 you will know that a lot of the new APIs require that you know the Package Family Name of the app you’re trying to communicate with. If you haven’t been following along, my Build talk here is a great starting point.
One convenient way to find out the PackageFamilyName of your app is to simply spit it out using the Windows.ApplicationModel.Package.Current.Id.FamilyName API. The always helpful dev center team just lit up another convenient way to look up this same information. If your app is already in the Windows store (Windows and Windows Phone store are now one) you can use the new preview dashboard. To do this, go to the new dashboard, select your app on the left and then go to App Management->App Identity. You should see the PackageFamilyName on the right.
Here’s a screenshot based on an app I’ve got published in the Windows Phone store:
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.