啟動應用程式以取得結果

重要 API

了解如何從某個應用程式啟動另一個應用程式,以及在這兩者間交換資料的方式。 這稱為 啟動應用程式以獲得結果。 這裡的範例示範如何使用 LaunchUriForResultsAsync 來啟動應用程式以取得結果。

Windows 10 中新的應用程式到應用程式通訊 API 使 Windows 應用程式 (和 Windows Web 應用程式) 可以啟動應用程式並交換資料和檔案。 這使您能夠從多個應用程式建立混搭解決方案。 使用這些新的 API,需要使用者使用多個應用程式的複雜工作現在可以無縫處理。 例如,您的應用程式可以啟動社交網路應用程式來選擇聯絡人,或啟動結帳應用程式來完成付款流程。

您為獲取結果而啟動的應用程式將稱為已啟動的應用程式。 啟動應用程式的應用程式將稱為呼叫應用程式。 對於此範例,您將編寫呼叫應用程式和啟動的應用程式。

第 1 步:註冊要在您將啟動以獲取結果的應用程式中處理的協議

在啟動的<應用程式>的 Package.appxmanifest 檔案中,將協定擴充新增至應用程式部分。 這裡的範例會使用名為 test-app2app 的虛構通訊協定。

協定擴充中的 ReturnResults 屬性接受下列值之一:

在此協定擴充範例中,只能為結果啟動應用程式。 這會簡化 OnActivated 方法內的邏輯,如下所述,因為我們必須只處理「針對結果啟動」案例,而不是啟動應用程式的其他方式。

<Applications>
   <Application ...>

     <Extensions>
       <uap:Extension Category="windows.protocol">
         <uap:Protocol Name="test-app2app" ReturnResults="always">
           <uap:DisplayName>Test app-2-app</uap:DisplayName>
         </uap:Protocol>
       </uap:Extension>
     </Extensions>

   </Application>
</Applications>

步驟 2:覆寫您將針對結果啟動的應用程式中的 Application.OnActivated

如果啟動的應用程式中尚不存在此方法,請在 App.xaml.cs 中定義的 App 類別中建立它。

在允許您在社交網路中選擇朋友的應用程式中,此功能可能是您開啟人員選擇器頁面的地方。 在下一個範例中,啟動應用程式以取得結果時,會顯示名為 LaunchedForResultsPage 的頁面 。 確定 using 語句包含在檔案頂端。

using Windows.ApplicationModel.Activation;
...
protected override void OnActivated(IActivatedEventArgs args)
{
    // Window management
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
    }

    // Code specific to launch for results
    var protocolForResultsArgs = (ProtocolForResultsActivatedEventArgs)args;
    // Open the page that we created to handle activation for results.
    rootFrame.Navigate(typeof(LaunchedForResultsPage), protocolForResultsArgs);

    // Ensure the current window is active.
    Window.Current.Activate();
}
using namespace winrt::Windows::ApplicationModel::Activation;
...
protected override void OnActivated(IActivatedEventArgs args)
{
    // Window management
    Frame rootFrame{ nullptr };
    auto content = Window::Current().Content();
    if (content)
    {
        rootFrame = content.try_as<Frame>();
    }
    
    if (rootFrame == null)
    {
        rootFrame = Frame();
        Window::Current().Content(rootFrame);
    }

    // Code specific to launch for results
    auto protocolForResultsEventArgs{ args.as<ProtocolForResultsActivatedEventArgs>() };
    // Open the page that we created to handle activation for results.
    rootFrame.Navigate(xaml_typename<LaunchedForResultsPage>(), protocolForResultsArgs);

    // Ensure the current window is active.
    Window::Current().Activate();
}

由於 Package.appxmanifest 檔案中的協定擴充永遠指定 ReturnResults,因此剛剛顯示的程式碼可以 args 直接轉換為 ProtocolForResultsActivatedEventArgs,並且確信只有 ProtocolForResultsActivatedEventArgs 會傳送到此應用程式的 OnActivated。 如果您的 app 可以啟動結果以外的方式來啟動,您可以檢查 IActivatedEventArgs.Kind 屬性是否傳回 ActivationKind.ProtocolForResults,以判斷應用程式是否已針對結果啟動。

步驟 3:將 ProtocolForResultsOperation 欄位新增至您針對結果啟動的應用程式

private Windows.System.ProtocolForResultsOperation _operation = null;
Windows::System::ProtocolForResultsOperation _operation = nullptr;

您將使用 ProtocolForResultsOperation 欄位,在啟動的應用程式準備好將結果傳回給呼叫的應用程式時發出訊號。 在此範例中,欄位會新增至 LaunchedForResultsPage 類別,因為您將從該頁面完成 launch-for-results 作業,而且需要存取它。

步驟 4:在您啟動以取得結果的應用程式中覆寫 OnNavigatedTo()

覆寫頁面上的 OnNavigatedTo 方法,以在應用程式啟動時顯示結果。 如果這個方法還不存在,請在 <pagename> 中定義的頁面類別內建立它.xaml.cs。 確保文件頂部包含以下 using 語句:

using Windows.ApplicationModel.Activation
using namespace winrt::Windows::ApplicationModel::Activation;

OnNavigatedTo 方法中的 NavigationEventArgs 物件包含從呼叫應用程式傳遞的資料。 數據可能不超過 100KB,並儲存在 ValueSet 物件中。

在此範例程式碼中,啟動的應用程式期望從呼叫應用程式發送的資料位於名為 TestData 的鍵下的 ValueSet 中,因為這就是範例的呼叫應用程式編碼要傳送的資料。

using Windows.ApplicationModel.Activation;
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var protocolForResultsArgs = e.Parameter as ProtocolForResultsActivatedEventArgs;
    // Set the ProtocolForResultsOperation field.
    _operation = protocolForResultsArgs.ProtocolForResultsOperation;

    if (protocolForResultsArgs.Data.ContainsKey("TestData"))
    {
        string dataFromCaller = protocolForResultsArgs.Data["TestData"] as string;
    }
}
...
private Windows.System.ProtocolForResultsOperation _operation = null;
using namespace winrt::Windows::ApplicationModel::Activation;
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    auto protocolForResultsArgs = e.Parameter().try_as<ProtocolForResultsActivatedEventArgs>();
    // Set the ProtocolForResultsOperation field.
    _operation = protocolForResultsArgs.ProtocolForResultsOperation();

    if (protocolForResultsArgs.Data().HasKey("TestData"))
    {
        string dataFromCaller{ unbox_value<hstring>(protocolForResultsArgs.Data().Lookup("TestData")) };
    }
}
...
Windows::System::ProtocolForResultsOperation _operation = nullptr;

步驟 5:撰寫程式代碼以將數據傳回呼叫的應用程式

在啟動的應用程式中,使用 ProtocolForResultsOperation 將資料傳回呼叫的應用程式。 在此範例程式代碼中,會建立 ValueSet 物件,其中包含要傳回呼叫應用程式的值。 接著 ProtocolForResultsOperation 欄位會用來將值傳送至呼叫的應用程式。

    ValueSet result = new ValueSet();
    result["ReturnedData"] = "The returned result";
    _operation.ReportCompleted(result);
    ValueSet result;
    result.Insert("ReturnedData", "The returned result");
    _operation.ReportCompleted(result);

第 6 步:編寫程式碼來啟動應用程式以獲取結果並獲取返回的資料

從呼叫應用程式的非同步方法中啟動應用程式,如本範例程式碼所示。 請注意 using 陳述式,這是程式代碼編譯的必要陳述式:

using System.Threading.Tasks;
using Windows.System;
...

async Task<string> LaunchAppForResults()
{
    var testAppUri = new Uri("test-app2app:"); // The protocol handled by the launched app
    var options = new LauncherOptions();
    options.TargetApplicationPackageFamilyName = "67d987e1-e842-4229-9f7c-98cf13b5da45_yd7nk54bq29ra";

    var inputData = new ValueSet();
    inputData["TestData"] = "Test data";

    string theResult = "";
    LaunchUriResult result = await Windows.System.Launcher.LaunchUriForResultsAsync(testAppUri, options, inputData);
    if (result.Status == LaunchUriStatus.Success &&
        result.Result != null &&
        result.Result.ContainsKey("ReturnedData"))
    {
        ValueSet theValues = result.Result;
        theResult = theValues["ReturnedData"] as string;
    }
    return theResult;
}

在此範例中,包含金鑰 TestDataValueSet 被傳遞到啟動的應用程式。 啟動的應用程式會建立一個 ValueSet,其中包含名為 ReturnedData 的鍵,其中包含傳回給呼叫者的結果。

您必須先建置並部署要啟動以取得結果的應用程式,再執行呼叫的應用程式。 否則,LaunchUriResult.Status 會報告 LaunchUriStatus.AppUnavailable

當您設定 TargetApplicationPackageFamilyName 時,將需要已啟動應用程式的系列名稱。 取得系列名稱的其中一個方法是從啟動的應用程式內進行下列呼叫:

string familyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;

備註

本操作說明中的範例提供啟動應用程式以取得結果的 「hello world」 簡介。 需要注意的關鍵事項是,新的 LaunchUriForResultsAsync API 可讓您非同步啟動應用程式並透過 ValueSet 類別進行通訊。 透過 ValueSet 傳遞資料的限制為 100KB。 如果您需要傳遞較大的數據量,您可以使用 SharedStorageAccessManager 類別來共用檔案,以建立可在應用程式之間傳遞的檔案令牌。 例如,假設有名為 inputDataValueSet,您可以將令牌儲存至您想要與啟動的應用程式共用的檔案:

inputData["ImageFileToken"] = SharedStorageAccessManager.AddFile(myFile);

然後,透過 LaunchUriForResultsAsync 將它傳遞給啟動的應用程式。