App To App Communication In Universal Windows Platform

In this article, we will learn about app-to-app communication in Windows 10.

Some new and improved ways have been introduced in Windows 10 to ease communication between the apps.

Previously, if we wanted to launch another app and make it do something, there was no programmatic way of notifying us, that the action was completed. With the new “launch for results” feature in Windows 10, we can get the callback from the second app, after some operation completes.

Windows 10 provides a great API, which can open another app and perform the operations in the second app and finally send results back to the first app. The new LaunchUriForResultsAsync method relies on the TargetApplicationPackageFamilyName API to make two-way communication between the apps possible.

Step 1: Open Visual Studio 2015. Create a Blank Universal Windows project, name it ‘App1’.

The first step is making the app available to be launched by other apps. To do this, we need to add a protocol declaration to the app’s package manifest (Package.appxmanifest).

In the Package.appmanifest of App1, we have to define the protocols like:

  1. <Extensions>  
  2.         <uap:Extension Category="windows.protocol">  
  3.           <uap:Protocol Name="app1" ReturnResults="optional">  
  4.             <uap:Logo>Assets\StoreLogo.scale-100.png</uap:Logo>  
  5.             <uap:DisplayName>App1</uap:DisplayName>  
  6.           </uap:Protocol>  
  7.         </uap:Extension>  
  8.  </Extensions>  
Step 2: Similarly, create another Blank Universal Windows project, name it ‘App2’.

In the Package.appmanifest of App2, define the protocols, similar to the one, shown above.
  1. <Extensions>  
  2.         <uap:Extension Category="windows.protocol">  
  3.           <uap:Protocol Name="app2" ReturnResults="optional">  
  4.             <uap:Logo>Assets\StoreLogo.scale-100.png</uap:Logo>  
  5.             <uap:DisplayName>App2</uap:DisplayName>  
  6.           </uap:Protocol>  
  7.         </uap:Extension>  
  8. </Extensions>  
Step 3: Now in the App1, let’s add a button in MainPage.xaml with a click event to open another app.

Complete XAML code snippet
  1. <Page  
  2.     x:Class="App1.MainPage"  
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  5.     xmlns:local="using:App1"  
  6.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  7.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  8.     mc:Ignorable="d">  
  9.   
  10.     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
  11.         <Button Click="Button_Click">Open another app</Button>  
  12.     </Grid>  
  13. </Page>  
Step 4: In C# code at the backend, button click event will be:
  1. private async void Button_Click(object sender, RoutedEventArgs e)  
  2. {  
  3.     var protocol = "app2://";   //protocol name of second app that is defined in package.appmanifest of second app.  
  4.     var packageFamilyName = "7df22c17-5ec3-4de0-b903-c295473af4a0_syk1cnben41w6";  //This is derived from second app.  
  5.     var status = await Launcher.QueryUriSupportAsync(new Uri(protocol), LaunchQuerySupportType.UriForResults, packageFamilyName);  
  6.     if (status == LaunchQuerySupportStatus.Available)  
  7.     {  
  8.         var options = new LauncherOptions  
  9.         {  
  10.             TargetApplicationPackageFamilyName = packageFamilyName  
  11.         };  
  12.         var values = new ValueSet();  
  13.         values.Add("UserName""kishor");  
  14.         values.Add("Message""This is message from App 1");  
  15.         var result = await Launcher.LaunchUriForResultsAsync(new Uri(protocol), options, values);  
  16.         if ((result.Status == LaunchUriStatus.Success) && (result.Result != null))  
  17.         {  
  18.             var isUser = result.Result["IsUser"as string;  
  19.             var msg = result.Result["Message"as string;  
  20.             if (isUser == "true")  
  21.             {  
  22.                 var dialog = new MessageDialog(msg, "Success");  
  23.                 await dialog.ShowAsync();  
  24.             }  
  25.         }  
  26.     }  
  27. }  
Here, we will need a package family name and a protocol name of the second app.

To get the package family name, we need this following code, which gives the package family name of the app.
  1. var packageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;  
Step 5: Now, in the second app, we need to handle the protocol in OnActivated event in App.xaml.cs.

Thus, put this code in App.xaml.cs of App2.
  1. protected override void OnActivated(IActivatedEventArgs args)  
  2. {  
  3.     Frame rootFrame = Window.Current.Content as Frame;  
  4.     if (rootFrame == null)  
  5.     {  
  6.         rootFrame = new Frame();  
  7.         rootFrame.CacheSize = 1;  
  8.         Window.Current.Content = rootFrame;  
  9.     }  
  10.     if (args.Kind == ActivationKind.ProtocolForResults)  
  11.     {  
  12.         var pfrArgs = (ProtocolForResultsActivatedEventArgs)args;  
  13.         if (pfrArgs.CallerPackageFamilyName.Equals("6c2cea9e-22ae-4796-8cfa-5c29bfd3f557_syk1cnben41w6"))  //Package Family name of first app  
  14.         {  
  15.             rootFrame.Navigate(typeof(MainPage), pfrArgs);  
  16.         }  
  17.     }  
  18.     else  
  19.     {  
  20.         rootFrame.Navigate(typeof(MainPage));  
  21.     }  
  22.     Window.Current.Activate();  
  23. }  
Step 6: In MainPage.xaml of App2, let’s add few textblocks and button like:
  1. <Page  
  2.     x:Class="App2.MainPage"  
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  5.     xmlns:local="using:App2"  
  6.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  7.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  8.     mc:Ignorable="d">  
  9.   
  10.     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
  11.         <StackPanel Orientation="Vertical">  
  12.         <TextBlock FontSize="50" >This is app 2</TextBlock>  
  13.             <TextBlock FontSize="30" Name="Name" ></TextBlock>  
  14.             <TextBlock FontSize="30" Name="Message" ></TextBlock>  
  15.             <Button x:Name="ok_Btn" Content="Ok" HorizontalAlignment="Left" FontSize="40" Click="ok_Btn_Click"  VerticalAlignment="Top" Width="320"/>  
  16.         </StackPanel>  
  17.     </Grid>  
  18. </Page>  
Step 7: In the MainPage.xaml.cs code at the backend of App2, update your code with the following:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Diagnostics;  
  4. using System.IO;  
  5. using System.Linq;  
  6. using System.Runtime.InteropServices.WindowsRuntime;  
  7. using Windows.ApplicationModel.Activation;  
  8. using Windows.Foundation;  
  9. using Windows.Foundation.Collections;  
  10. using Windows.UI.Xaml;  
  11. using Windows.UI.Xaml.Controls;  
  12. using Windows.UI.Xaml.Controls.Primitives;  
  13. using Windows.UI.Xaml.Data;  
  14. using Windows.UI.Xaml.Input;  
  15. using Windows.UI.Xaml.Media;  
  16. using Windows.UI.Xaml.Navigation;  
  17.   
  18. namespace App2  
  19. {  
  20.     public sealed partial class MainPage : Page  
  21.     {  
  22.         private ProtocolForResultsActivatedEventArgs pfrArgs;  
  23.         private string userName;  
  24.         private string msg;  
  25.         public MainPage()  
  26.         {  
  27.             this.InitializeComponent();  
  28.             Loaded += MainPage_Loaded;  
  29.         }  
  30.   
  31.         private void MainPage_Loaded(object sender, RoutedEventArgs e)  
  32.         {  
  33.             var packageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName; //To get the package family name of this app which is needed in first app.  
  34.             Debug.WriteLine(packageFamilyName);  
  35.         }  
  36.   
  37.         protected override void OnNavigatedTo(NavigationEventArgs e)  
  38.         {  
  39.             pfrArgs = e.Parameter as ProtocolForResultsActivatedEventArgs;  
  40.             if (pfrArgs != null)  
  41.             {  
  42.                 userName = pfrArgs.Data["UserName"as string;  
  43.                 msg = pfrArgs.Data["Message"as string;  
  44.                 Name.Text = userName;  
  45.                 Message.Text = msg;  
  46.             }  
  47.         }  
  48.   
  49.         private void ok_Btn_Click(object sender, RoutedEventArgs e)  
  50.         {  
  51.             SuccessCallBack();  
  52.         }  
  53.         private void SuccessCallBack()  
  54.         {  
  55.             if (pfrArgs != null)  
  56.             {  
  57.                 var values = new ValueSet();  
  58.                 values.Add("Message""This is message from app 2");  
  59.                 values.Add("IsUser""true");  
  60.                 pfrArgs.ProtocolForResultsOperation.ReportCompleted(values);  
  61.             }  
  62.         }  
  63.     }  
  64. }  
Step 8: Run both the Applications. You can open App2 form App1 and pass the data from App2 to App1 as callback.

Find the complete project in GitHub.