Поделиться через


Глубокая ссылка из фонового приложения в Кортана в приложение переднего плана

Предупреждение

Эта функция больше не поддерживается в обновлении Windows 10 мая 2020 г. (версия 2004, имя кода "20H1").

Укажите глубокие ссылки из фонового приложения в Кортана , который запускает приложение на переднем плане в определенном состоянии или контексте.

Примечание.

Кортана и фоновая служба приложений завершаются при запуске приложения переднего плана.

Глубокая ссылка отображается по умолчанию на экране завершения Кортаны , как показано здесь ("Перейти к AdventureWorks"), но вы можете отображать глубокие ссылки на различных других экранах.

Снимок экрана: завершение фонового приложения Кортаны для предстоящей поездки

Обзор

Пользователи могут получить доступ к приложению через Кортана , выполнив следующие действия.

Здесь мы обсудим глубокую связь.

Глубокая компоновка полезна, если Кортана и служба приложений действуют в качестве шлюза для полнофункционированного приложения (вместо того, чтобы пользователь запускал приложение через меню ), или для предоставления доступа к более подробным и функциональным возможностям в приложении, которое невозможно получить через Кортана. Глубокая компоновка — это еще один способ повысить удобство использования и повысить удобство использования приложения.

Существует три способа предоставления глубоких ссылок:

  • Ссылка "Перейти к приложению<>" на различных экранах Кортаны.
  • Ссылка, внедренная в плитку содержимого на различных экранах Кортаны .
  • Программное запуск приложения переднего плана из фоновой службы приложений.

Кортана отображает глубокую ссылку "Перейти к <приложению>" под карточкой содержимого на большинстве экранов.

Снимок экрана: глубокая ссылка Кортаны

Вы можете указать аргумент запуска для этой ссылки, открывающую приложение в аналогичном контексте, как и служба приложений. Если аргумент запуска не указан, приложение запускается на главном экране.

В этом примере из AdventureWorksVoiceCommandService.cs примера AdventureWorks мы передаем указанную строку назначения (destination) методу SendCompletionMessageForDestination, который извлекает все соответствующие поездки и предоставляет глубокую ссылку на приложение.

Во-первых, мы создадим VoiceCommandUserMessage (userMessage), который говорил Кортана и показан на холсте Кортаны. Затем создается объект списка VoiceCommandContentTile для отображения коллекции карт результатов на холсте.

Затем эти два объекта передаются в метод CreateResponse объекта VoiceCommandResponse ().response Затем мы зададим значение свойства AppLaunchArgument объекта ответа значением переданного destination этой функции. Когда пользователь нажимает плитку содержимого на холсте Кортаны, значения параметров передаются приложению через объект ответа.

Наконец, мы вызываем метод ReportSuccessAsync voiceCommandServiceConnection.

/// <summary>
/// Show details for a single trip, if the trip can be found. 
/// This demonstrates a simple response flow in Cortana.
/// </summary>
/// <param name="destination">The destination specified in the voice command.</param>
private async Task SendCompletionMessageForDestination(string destination)
{
...
    IEnumerable<Model.Trip> trips = store.Trips.Where(p => p.Destination == destination);

    var userMessage = new VoiceCommandUserMessage();
    var destinationsContentTiles = new List<VoiceCommandContentTile>();
...
    var response = VoiceCommandResponse.CreateResponse(userMessage, destinationsContentTiles);

    if (trips.Count() > 0)
    {
        response.AppLaunchArgument = destination;
    }

    await voiceServiceConnection.ReportSuccessAsync(response);
}

Вы можете добавить глубокие ссылки на карточки содержимого на различных экранах Кортаны .

Снимок экрана: холст Кортаны для завершения фонового потока приложения Кортаны с помощью AdventureWorks предстоящей поездки с раздаткойAdventureWorks "Предстоящее путешествие" с экраном передачи

Как и ссылки "Перейти к <приложению>", вы можете предоставить аргумент запуска, чтобы открыть приложение с аналогичным контекстом, как и служба приложений. Если аргумент запуска не указан, плитка содержимого не связывается с приложением.

В этом примере из AdventureWorksVoiceCommandService.cs примера AdventureWorks мы передаем указанное назначение методу SendCompletionMessageForDestination, который извлекает все соответствующие поездки и предоставляет карточки содержимого с глубокими ссылками на приложение.

Во-первых, мы создадим VoiceCommandUserMessage (userMessage), который говорил Кортана и показан на холсте Кортаны. Затем создается объект списка VoiceCommandContentTile для отображения коллекции карт результатов на холсте.

Затем эти два объекта передаются в метод CreateResponse объекта VoiceCommandResponse ().response Затем мы задали значение свойства AppLaunchArgument значением назначения в голосовой команде.

Наконец, мы вызываем метод ReportSuccessAsync voiceCommandServiceConnection. Здесь мы добавим две плитки содержимого с разными значениями параметров AppLaunchArgument в список VoiceCommandContentTile, используемый в вызове ReportSuccessAsync объекта VoiceCommandServiceConnection.

/// <summary>
/// Show details for a single trip, if the trip can be found. 
/// This demonstrates a simple response flow in Cortana.
/// </summary>
/// <param name="destination">The destination specified in the voice command.</param>
private async Task SendCompletionMessageForDestination(string destination)
{
    // If this operation is expected to take longer than 0.5 seconds, the task must
    // supply a progress response to Cortana before starting the operation, and
    // updates must be provided at least every 5 seconds.
    string loadingTripToDestination = string.Format(
               cortanaResourceMap.GetValue("LoadingTripToDestination", cortanaContext).ValueAsString,
               destination);
    await ShowProgressScreen(loadingTripToDestination);
    Model.TripStore store = new Model.TripStore();
    await store.LoadTrips();

    // Query for the specified trip. 
    // The destination should be in the phrase list. However, there might be  
    // multiple trips to the destination. We pick the first.
    IEnumerable<Model.Trip> trips = store.Trips.Where(p => p.Destination == destination);

    var userMessage = new VoiceCommandUserMessage();
    var destinationsContentTiles = new List<VoiceCommandContentTile>();
    if (trips.Count() == 0)
    {
        string foundNoTripToDestination = string.Format(
               cortanaResourceMap.GetValue("FoundNoTripToDestination", cortanaContext).ValueAsString,
               destination);
        userMessage.DisplayMessage = foundNoTripToDestination;
        userMessage.SpokenMessage = foundNoTripToDestination;
    }
    else
    {
        // Set plural or singular title.
        string message = "";
        if (trips.Count() > 1)
        {
            message = cortanaResourceMap.GetValue("PluralUpcomingTrips", cortanaContext).ValueAsString;
        }
        else
        {
            message = cortanaResourceMap.GetValue("SingularUpcomingTrip", cortanaContext).ValueAsString;
        }
        userMessage.DisplayMessage = message;
        userMessage.SpokenMessage = message;

        // Define a tile for each destination.
        foreach (Model.Trip trip in trips)
        {
            int i = 1;
            
            var destinationTile = new VoiceCommandContentTile();

            destinationTile.ContentTileType = VoiceCommandContentTileType.TitleWith68x68IconAndText;
            destinationTile.Image = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///AdventureWorks.VoiceCommands/Images/GreyTile.png"));

            destinationTile.AppLaunchArgument = trip.Destination;
            destinationTile.Title = trip.Destination;
            if (trip.StartDate != null)
            {
                destinationTile.TextLine1 = trip.StartDate.Value.ToString(dateFormatInfo.LongDatePattern);
            }
            else
            {
                destinationTile.TextLine1 = trip.Destination + " " + i;
            }

            destinationsContentTiles.Add(destinationTile);
            i++;
        }
    }

    var response = VoiceCommandResponse.CreateResponse(userMessage, destinationsContentTiles);

    if (trips.Count() > 0)
    {
        response.AppLaunchArgument = destination;
    }

    await voiceServiceConnection.ReportSuccessAsync(response);
}

Вы также можете программно запустить приложение с аргументом запуска, чтобы открыть приложение с аналогичным контекстом, как служба приложений. Если аргумент запуска не указан, приложение запускается на главном экране.

Здесь мы добавим параметр AppLaunchArgument со значением "Лас-Вегас" в объект VoiceCommandResponse, используемый в вызове RequestAppLaunchAsync объекта VoiceCommandServiceConnection.

var userMessage = new VoiceCommandUserMessage();
userMessage.DisplayMessage = "Here are your trips.";
userMessage.SpokenMessage = 
  "You have one trip to Vegas coming up.";

response = VoiceCommandResponse.CreateResponse(userMessage);
response.AppLaunchArgument = "Las Vegas";
await  VoiceCommandServiceConnection.RequestAppLaunchAsync(response);

Манифест приложения

Чтобы включить глубокую windows.personalAssistantLaunch связь с приложением, необходимо объявить расширение в файле Package.appxmanifest проекта приложения.

Здесь мы объявляем windows.personalAssistantLaunch расширение для приложения Adventure Works .

<Extensions>
  <uap:Extension Category="windows.appService" 
    EntryPoint="AdventureWorks.VoiceCommands.AdventureWorksVoiceCommandService">
    <uap:AppService Name="AdventureWorksVoiceCommandService"/>
  </uap:Extension>
  <uap:Extension Category="windows.personalAssistantLaunch"/> 
</Extensions>

Контракт протокола

Приложение запускается на переднем плане с помощью активации универсального идентификатора ресурса (URI) с помощью контракта протокола . Приложение должно переопределить событие OnActivated приложения и проверить наличие протокола ActivationKind. Дополнительные сведения см. в разделе "Обработка активации URI".

Здесь мы декодируем универсальный код ресурса (URI), предоставленный протоколом ProtocolActivatedEventArgs для доступа к аргументу запуска. В этом примере URI имеет значение "windows.personalassistantlaunch:? LaunchContext=Лас-Вегас".

if (args.Kind == ActivationKind.Protocol)
  {
    var commandArgs = args as ProtocolActivatedEventArgs;
    Windows.Foundation.WwwFormUrlDecoder decoder = 
      new Windows.Foundation.WwwFormUrlDecoder(commandArgs.Uri.Query);
    var destination = decoder.GetFirstValueByName("LaunchContext");

    navigationCommand = new ViewModel.TripVoiceCommand(
      "protocolLaunch",
      "text",
      "destination",
      destination);

    navigationToPageType = typeof(View.TripDetails);

    rootFrame.Navigate(navigationToPageType, navigationCommand);

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