2015-09-01 27 views
2

我想写一个c#programm来定义cortana的自定义命令!cortana自己的命令在backgroundtask

首先我创建一个默认的应用程序的应用程序并加载VCD文件的...

我创建第二个项目链接这主要项目,并创建这个backgroundtask内处理柯塔娜的请求!

现在cortana知道我的命令,但是如果我告诉她她正在回答“Es ist etwas schief gelaufen”(英语:“it failed”)。

我认为BackgroundTask没有正确调用。

App.cs

namespace CortanaCommandsStart 
{ 
/// <summary> 
/// Stellt das anwendungsspezifische Verhalten bereit, um die Standardanwendungsklasse zu ergänzen. 
/// </summary> 
sealed partial class App : Application 
{ 
    /// <summary> 
    /// Initialisiert das Singletonanwendungsobjekt. Dies ist die erste Zeile von erstelltem Code 
    /// und daher das logische Äquivalent von main() bzw. WinMain(). 
    /// </summary> 
    public App() 
    { 
     Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(Microsoft.ApplicationInsights.WindowsCollectors.Metadata | Microsoft.ApplicationInsights.WindowsCollectors.Session); 
     this.InitializeComponent(); 
     this.Suspending += OnSuspending; 
    } 

    /// <summary> 
    /// Wird aufgerufen, wenn die Anwendung durch den Endbenutzer normal gestartet wird. Weitere Einstiegspunkte 
    /// werden z. B. verwendet, wenn die Anwendung gestartet wird, um eine bestimmte Datei zu öffnen. 
    /// </summary> 
    /// <param name="e">Details über Startanforderung und -prozess.</param> 
    protected override async void OnLaunched(LaunchActivatedEventArgs e) 
    { 
     Frame rootFrame = Window.Current.Content as Frame; 

     // App-Initialisierung nicht wiederholen, wenn das Fenster bereits Inhalte enthält. 
     // Nur sicherstellen, dass das Fenster aktiv ist. 
     if (rootFrame == null) 
     { 
      // Frame erstellen, der als Navigationskontext fungiert und zum Parameter der ersten Seite navigieren 
      rootFrame = new Frame(); 

      rootFrame.NavigationFailed += OnNavigationFailed; 

      if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 
      { 
       //TODO: Zustand von zuvor angehaltener Anwendung laden 
      } 

      // Den Frame im aktuellen Fenster platzieren 
      Window.Current.Content = rootFrame; 
     } 

     if (rootFrame.Content == null) 
     { 
      // Wenn der Navigationsstapel nicht wiederhergestellt wird, zur ersten Seite navigieren 
      // und die neue Seite konfigurieren, indem die erforderlichen Informationen als Navigationsparameter 
      // übergeben werden 
      rootFrame.Navigate(typeof(MainPage), e.Arguments); 
     } 

     try { 
      StorageFile vcdStorageFile = await Package.Current.InstalledLocation.GetFileAsync(@"LEDControll.xml"); 
      await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdStorageFile); 
      System.Diagnostics.Debug.WriteLine("There was no error registering the Voice Command Definitions"); 
     } 
     catch (Exception ex) 
     { 
      System.Diagnostics.Debug.WriteLine("There was an error registering the Voice Command Definitions", ex); 
     } 

     // Sicherstellen, dass das aktuelle Fenster aktiv ist 
     Window.Current.Activate(); 
    } 

    /// <summary> 
    /// Wird aufgerufen, wenn die Navigation auf eine bestimmte Seite fehlschlägt 
    /// </summary> 
    /// <param name="sender">Der Rahmen, bei dem die Navigation fehlgeschlagen ist</param> 
    /// <param name="e">Details über den Navigationsfehler</param> 
    void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 
    { 
     throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 
    } 

    /// <summary> 
    /// Wird aufgerufen, wenn die Ausführung der Anwendung angehalten wird. Der Anwendungszustand wird gespeichert, 
    /// ohne zu wissen, ob die Anwendung beendet oder fortgesetzt wird und die Speicherinhalte dabei 
    /// unbeschädigt bleiben. 
    /// </summary> 
    /// <param name="sender">Die Quelle der Anhalteanforderung.</param> 
    /// <param name="e">Details zur Anhalteanforderung.</param> 
    private void OnSuspending(object sender, SuspendingEventArgs e) 
    { 
     var deferral = e.SuspendingOperation.GetDeferral(); 
     //TODO: Anwendungszustand speichern und alle Hintergrundaktivitäten beenden 
     deferral.Complete(); 
    } 
} 
} 

Appxmanifest:

<?xml version="1.0" encoding="utf-8"?> 
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp"> 
    <Identity Name="32ed3ec5-2e4a-4517-ae2b-842653ab8a8e" Publisher="CN=Flo" Version="1.0.0.0" /> 
    <mp:PhoneIdentity PhoneProductId="32ed3ec5-2e4a-4517-ae2b-842653ab8a8e" PhonePublisherId="00000000-0000-0000-0000-000000000000" /> 
    <Properties> 
    <DisplayName>CortanaCommandsStart</DisplayName> 
    <PublisherDisplayName>Flo</PublisherDisplayName> 
    <Logo>Assets\StoreLogo.png</Logo> 
    </Properties> 
    <Dependencies> 
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" /> 
    </Dependencies> 
    <Resources> 
    <Resource Language="x-generate" /> 
    </Resources> 
    <Applications> 
    <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="CortanaCommandsStart.App"> 
     <uap:VisualElements DisplayName="CortanaCommandsStart" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="CortanaCommandsStart" BackgroundColor="transparent"> 
     <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"> 
     </uap:DefaultTile> 
     <uap:SplashScreen Image="Assets\SplashScreen.png" /> 
     </uap:VisualElements> 

     <Extensions> 
     <uap:Extension Category="windows.appService" EntryPoint="CortanaCommand.CortanaCommandService"> 
      <uap:AppService Name="CortanaCommandService" /> 
     </uap:Extension> 
     </Extensions> 

    </Application> 
    </Applications> 
</Package> 

CortanaCommand.cs

namespace CortanaCommand 
{ 
    public sealed class CortanaCommandService : IBackgroundTask 
    { 
     private VoiceCommandServiceConnection voiceServiceConnection; 
     private BackgroundTaskDeferral _deferral; 

     public async void Run(IBackgroundTaskInstance taskInstance) 
     { 
      _deferral = taskInstance.GetDeferral(); 

      voiceServiceConnection.VoiceCommandCompleted += VoiceCommandCompleted; 

      AppServiceTriggerDetails triggerDetails = taskInstance.TriggerDetails as AppServiceTriggerDetails; 

      if (triggerDetails != null && triggerDetails.Name.Equals("CortanaCommandService")) 
      { 
       try 
       { 
        voiceServiceConnection = VoiceCommandServiceConnection.FromAppServiceTriggerDetails(triggerDetails); 
        VoiceCommand voiceCommand = await voiceServiceConnection.GetVoiceCommandAsync(); 

        // Perform the appropriate command depending on the operation defined in VCD 
        VoiceCommandUserMessage userMessage = new VoiceCommandUserMessage(); 
        switch (voiceCommand.CommandName) 
        { 
         case "LedChangeColor": 
          var destination = voiceCommand.Properties["color"][0]; 
          SendCompletionMessageForDestination(destination); 
          break; 
         default: 
          LaunchAppInForeground(); 
          break; 
        } 
       } 
       finally 
       { 
        _deferral.Complete(); 
       } 
      } 

     } 

     private void VoiceCommandCompleted(VoiceCommandServiceConnection sender, VoiceCommandCompletedEventArgs args) 
     { 
      if (this._deferral != null) 
      { 
       this._deferral.Complete(); 
      } 
     } 

     private async void SendCompletionMessageForDestination(string destination) 
     { 
      // Take action and determine when the next trip to destination 
      // Inset code here 

      // Replace the hardcoded strings used here with strings 
      // appropriate for your application. 

      // First, create the VoiceCommandUserMessage with the strings 
      // that Cortana will show and speak. 
      var userMessage = new VoiceCommandUserMessage(); 
      userMessage.DisplayMessage = "Here’s your trip."; 
      userMessage.SpokenMessage = "Your trip to Vegas is on August 3rd."; 

      // Optionally, present visual information about the answer. 
      // For this example, create a VoiceCommandContentTile with an 
      // icon and a string. 
      var destinationsContentTiles = new List<VoiceCommandContentTile>(); 

      // Create the VoiceCommandResponse from the userMessage and list  
      // of content tiles. 
      var response = VoiceCommandResponse.CreateResponse(userMessage, destinationsContentTiles); 

      // Ask Cortana to display the user message and content tile and 
      // also speak the user message. 
      await voiceServiceConnection.ReportSuccessAsync(response); 
     } 

     private async void LaunchAppInForeground() 
     { 
      var userMessage = new VoiceCommandUserMessage(); 
      userMessage.SpokenMessage = "Launching Adventure Works"; 

      var response = VoiceCommandResponse.CreateResponse(userMessage); 

      // When launching the app in the foreground, pass an app 
      // specific launch parameter to indicate what page to show. 
      response.AppLaunchArgument = "showAllTrips=true"; 

      await voiceServiceConnection.RequestAppLaunchAsync(response); 
     } 
    } 
} 

VCD:

<?xml version="1.0" encoding="utf-8"?> 
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2"> 

    <CommandSet xml:lang="de-de" Name="LEDControll"> 
    <CommandPrefix>LED</CommandPrefix> 
    <Example>Steuere die LEDs</Example> 

    <Command Name="LedChangeColor"> 
     <Example>LED Farbe grün</Example> 
     <ListenFor>farbe {color}</ListenFor> 
     <Feedback>Farbe wird geändert in {color}</Feedback> 
     <VoiceCommandService Target="CortanaCommandService"/> 
    </Command> 

    <PhraseList Label="color"> 
     <Item> grün </Item> 
     <Item> blau </Item> 
     <Item> rot </Item> 
    </PhraseList> 

    </CommandSet> 

</VoiceCommands> 

谢谢你的帮助!

+1

您是否已将后台任务项目添加为启动项目的引用依赖项,以便将其部署?没有它,什么都不会告诉VS实际部署后台任务。 –

+0

是不是该行: Flo

+1

否。包清单不控制Visual Studio的构建,链接和复制行为。你想去你的主要启动项目(最有可能存放App.cs的项目)的References部分,并且添加一个对后台任务项目的引用。程序包清单扩展条目只是一个告诉Windows应用程序包内有后台服务的机制。 –

回答

1

这里只是将答案所以很清楚:

为了保证后台任务添加到应用程序包正确,您可以从启动项目中VS后台任务项目中添加一个参考:

  1. 在启动项目
  2. 转到引用单击鼠标右键添加引用
  3. 选择“项目”中的下一个离开
  4. 勾选框到包含后台任务的项目。
  5. 点击确定。

这可以确保当您部署它时,VS会构建并将后台任务复制到包中。否则,你很难调试这样的问题。

通常情况下,如果您已经三重检查了Package manifest uap:Extension条目是否具有正确的详细信息,但在尝试激活它时无法在后台任务中获得断点。我还会检查是否有任何事件日志类型条目可以更容易查看。

相关问题