결과를 위한 앱 실행

중요 API

다른 앱에서 앱을 시작하고 두 사이에서 데이터를 교환하는 방법을 알아봅니다. 이를 결과 확인을 위해 앱 시작하기라고 합니다 이 예제에서는 결과를 확인하기 위해 LaunchUriForResultsAsync를 사용하여 앱을 시작하는 방법을 보여줍니다.

Windows 10의 새로운 앱 간 통신 API를 사용하면 Windows 앱(및 Windows 웹앱)에서 앱을 시작하고 데이터 및 파일을 교환할 수 있습니다. 이렇게 하면 여러 앱에서 매시업 솔루션을 빌드할 수 있습니다. 이 새로운 API를 사용하면 사용자가 여러 앱을 사용해야 했던 복잡한 작업을 이제 원활하게 처리할 수 있습니다. 예를 들면 앱에서 소셜 네트워킹 앱을 시작하여 연락처를 선택하거나, 체크아웃 앱을 시작하여 결제 프로세스를 완료할 수 있습니다.

결과를 확인하기 위해 시작할 앱은 시작 대상 앱이라고 합니다. 앱을 시작하는 앱은 호출 앱이라고 합니다. 이 예제에서는 호출 앱과 시작 대상 앱을 모두 작성합니다.

1단계: 결과를 확인하기 위해 시작할 앱에서 처리할 프로토콜을 등록합니다.

시작 대상 앱의 Package.appxmanifest 파일에서 프로토콜 확장을 <애플리케이션> 섹션에 추가하세요. 이 예제에서는 test-app2app이라는 가상 프로토콜을 사용합니다.

프로토콜 확장의 ReturnResults 특성은 다음 값 중 하나를 허용합니다.

  • 선택 사항LaunchUriForResultsAsync 메서드를 사용해서 결과를 확인하기 위해 앱을 시작하거나, LaunchUriAsync를 사용해서 결과를 볼 수 없도록 앱을 시작할 수 있습니다. 선택 사항을 사용하는 경우, 시작 대상 앱은 스스로가 결과를 확인하기 위해 시작되었는지 여부를 판단해야 합니다. 이 작업은 OnActivated 이벤트 인수를 검사해서 수행할 수 있습니다. 이 인수의 IActivatedEventArgs.Kind 속성이 ActivationKind.ProtocolForResults를 반환하거나, 해당 이벤트 인수의 형식이 ProtocolActivatedEventArgs인 경우, LaunchUriForResultsAsync를 통해 앱이 시작되었습니다.
  • 상시—결과를 확인하기 위해서만 앱을 시작할 수 있습니다. 다시 말해, 앱은 LaunchUriForResultsAsync에만 응답할 수 있습니다.
  • 없음—결과를 확인하기 위해 앱을 시작할 수 없습니다. 앱은 LaunchUriAsync에만 응답할 수 있습니다.

이 프로토콜 확장 예제에서는 결과를 확인하기 위해서만 앱을 시작할 수 있습니다. 이는 아래에 설명된 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상시로 지정합니다. 따라서 표시된 코드는 이 앱에 대해 ProtocolForResultsActivatedEventArgs만이 OnActivated로 전송된다는 확신 하에 args을(를) 직접 ProtocolForResultsActivatedEventArgs로 캐스팅할 수 있습니다. 결과를 확인하기 위해 시작하는 것 이외의 방법으로 앱을 활성화할 수 있는 경우, IActivatedEventArgs.Kind 속성이 결과 확인을 위해 앱이 시작되었는지 여부를 알아보기 위해 ActivationKind.ProtocolForResults를 반환했는지 여부를 검사할 수 있습니다.

3단계: 결과 확인을 위해 시작하는 앱에 ProtocolForResultsOperation 필드를 추가합니다.

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

시작 대상 앱이 호출 앱에 결과를 반환할 준비가 되면 ProtocolForResultsOperation 필드를 사용하여 신호를 보냅니다. 이 예제에서는 해당 필드가 LaunchedForResultsPage 클래스에 추가되는데, 이는 해당 페이지에서 결과 확인용 시작 작업을 완료하고 해당 작업에 액세스해야 하기 때문입니다.

4단계: 결과 확인을 위해 시작하는 앱에서 OnNavigatedTo()를 재정의합니다.

결과 확인을 위해 앱을 시작할 경우 표시할 페이지에서 OnNavigatedTo 메서드를 재정의하세요. 이 메서드가 아직 없다면 <pagename>.xaml.cs에 정의된 페이지에 대한 클래스 내부에서 해당 메서드를 생성하세요. 다음 using 구문이 파일의 맨 위에 포함되어 있는지 확인하세요.

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

OnNavigatedTo 메서드의 NavigationEventArgs 개체에는 호출 앱으로부터 전달된 데이터가 담겨 있습니다. 이 데이터는 100KB를 초과하지 않을 수 있으며 ValueSet 개체에 저장됩니다.

이 예제 코드에서 시작 대상 앱은 호출 앱에서 전송한 데이터가 TestData라는 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;
}

이 예제에서는 TestData 키가 담긴 ValueSet가 시작 대상 앱에 전달됩니다. 시작 대상 앱은 호출자에게 반환된 결과가 담긴 ReturnedData라는 키를 사용하여 ValueSet를 생성합니다.

호출 앱을 실행하기 전에 결과 확인을 위해 시작할 앱을 빌드하고 배포해야 합니다. 그렇지 않으면 LaunchUriResult.StatusLaunchUriStatus.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를 통해 이를 시작 대상 앱에 전달하세요.