我正在尝试编写一个c#程序来为cortana定义自定义命令!
首先,我创建一个默认的应用程序应用程序并加载VCD文件...
我创建了第二个项目,将其链接到主项目,并在其中创建了一个后台任务来处理cortana请求!
现在,Cortana知道了我的命令,但是如果我告诉她一些事情,她会回答“ Es ist etwas schief gelaufen”(英语:“失败”)。
我认为BackgroundTask没有正确调用。
应用程式
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>
谢谢您的帮助!
最佳答案
只需在此处添加答案即可,很明显:
为了确保将后台任务正确添加到App Package中,可以在VS中将从启动项目的引用添加到后台任务项目中:
右键单击启动项目中的引用
转到添加参考
选择左侧的“项目”
选中包含后台任务的项目旁边的框。
点击确定。
这样可以确保VS在您进行部署时将构建后台任务并将其复制到程序包中。否则,您将遇到难以调试的问题。
通常,当您对软件包清单uap:Extension条目具有正确的详细信息进行三重检查时,您就可以知道发生了这种情况,但是当您尝试激活它时却无法在后台任务中找到断点。我还将检查是否可以查看任何事件日志类型条目,以便更轻松地查看。
关于c# - cortana自己在backgroundtask中的命令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32337008/