2017-01-06 3 views
1

Ich arbeite derzeit an UWP-Projekt in der Lage zu steuern andere App Hintergrund Media Player Instanz, ich. e .:Fire System-Event, um andere Anwendungen zu steuern MediaPlayer

MediaPlayer player = BackgroundMediaPlayer.Current; 

Als ich auf MSDN official documentation of MedaPlayer class gefunden - es Lied Überspringen oder bewegt zu vorherigen keine direkte Methode ist.

Ich habe für eine Lösung selbst für einige Tage suchen, bis ich auf so etwas wie dieses bekam:
(Fireevent von here - modifizierte einer Zeile auf UWP zu arbeiten)

private async void button3_Click(object sender, RoutedEventArgs e) 
{ 
    MediaPlayer player = BackgroundMediaPlayer.Current; 
    SystemMediaTransportControls d; 
    await Task.Factory.StartNew(() => { d = player.SystemMediaTransportControls; }); 

    await FireEvent(d, "ButtonPressed", new FakeEventArgs(SystemMediaTransportControlsButton.Next)); 
} 

public async Task FireEvent(object onMe, string invokeMe, params object[] eventParams) 
{ 
    MulticastDelegate eventDelagate = (MulticastDelegate)onMe.GetType().GetField(invokeMe, 
             BindingFlags.Instance | 
             BindingFlags.NonPublic).GetValue(onMe); 

    Delegate[] delegates = eventDelagate.GetInvocationList(); 

    foreach (Delegate dlg in delegates) 
    { 
     dlg.DynamicInvoke(dlg.Target, eventParams); 
    } 
} 

Obwohl ich selbst gemacht sicher, dass auf meinem Test Telefon gibt es eine Musik zu spielen, nach Linie definieren eventDelegate ich:

Exception thrown: 'System.NullReferenceException' in foo.exe 

Was mache ich falsch? Gibt es eine andere Art zu schießen und Ereignis? Oder sogar eine andere Methode, um den MediaPlayer anderer Apps zu steuern?

EDIT 1 FakeEventArgs als Äquivalent SystemMediaTransportControlsButtonPressedEventArgs gemacht wird, verursachen diese Klasse nicht konstruierbar ist, wie hier:

public sealed class FakeEventArgs 
{ 
    SystemMediaTransportControlsButton Button = SystemMediaTransportControlsButton.Pause; 

    public FakeEventArgs (SystemMediaTransportControlsButton But) 
    { 
     Button = But; 
    } 
} 
+0

Es ist ein wenig unklar, wo Sie die "NullReferenceException" bekommen, ist es auf der 'eventDelagate' Deklaration oder auf dem' eventDelagate.GetInvocationList() 'Aufruf? Es würde helfen, wenn Sie Ihre Stack-Trace in Ihre Frage aufnehmen würden. – gmiley

+0

Auf der Deklaration kann ich Stack-Trace aufgrund von Fehlern in Visual Studio nicht anzeigen. – Hypixus

+0

Verifizieren Sie, dass Sie tatsächlich eine Instanz eines Objekts an den 'FireEvent'-Aufruf übergeben? Überprüfen Sie, ob Ihre Variable "d" nicht null ist, bevor Sie versuchen, eine Aktion für sie auszuführen. – gmiley

Antwort

0

Hier gibt es eine Reihe von Fragen sind.

Erstens erwartete ich die Prozessisolierung und das Sicherheitsmodell, um zu verhindern, dass irgendeine App (nicht nur Ihre) diese Art von Aufgabe ausführen kann. Die Kontrolle über die Musikwiedergabe ist bei Metro/Modern/UWP-Apps nur sehr eingeschränkt möglich. Du kannst deine eigene Musik spielen, aber du kannst auf Systemebene nicht viel tun oder eine andere App beeinflussen, die Musik spielt. Wenn Sie Musik wiedergeben, können Sie sie anhalten. Wenn eine andere App Musik abspielt, können Sie die Wiedergabe von Musik steuern. Als allgemeine Regel, wenn Sie nicht möchten, dass andere Apps potentiell schädliche Dinge tun, oder wenn die System-Benutzeroberfläche etwas steuert, können Sie selbst nicht viel damit machen.

Wie auch immer, Ihr Code sah interessant aus, also dachte ich, dass es sich lohnt, zu erkunden. Möglicherweise haben Sie eine interessante Problemumgehung gefunden.
Hier sind die spezifischen Probleme, die ich gefunden habe.

  1. Die Zuweisung von d muss nicht asynchron durchgeführt werden. Aus keinem Grund, den ich sehen kann, erstellen und starten Sie eine neue Aufgabe, um d einen Wert zuzuweisen. Da dies nicht asynchron erfolgen muss, können Sie dies als Teil des normalen Codeflusses in der Klickmethode tun.
  2. Die Methode FireEvent muss nicht asynchron sein, und Sie möchten nicht, dass sie eine Aufgabe zurückgibt, sondern nur ausgeführt werden soll. Der Code wird funktionieren und einfacher sein, wenn die Signatur public void FireEvent(... lautet.
  3. Jetzt bekommen wir, warum der Code nie funktionieren würde. Der Typ SystemMediaTransportControls hat kein Feld namens "ButtonPressed". (Oder irgendwelche Felder für die Angelegenheit.) Wenn der Code GetValue(onMe) läuft es immer durch eine NullReferenceException. Von da an gibt es nichts mehr, was Sie dynamisch aufrufen können.

Ich denke, Sie müssen Ihre App Idee zu überdenken. Es ist nicht möglich, eine UWP-App willkürlich von einer anderen UWP-App aus zu steuern, es sei denn, die Ziel-App stellt ausdrücklich eine Möglichkeit dafür zur Verfügung.
Die andere Frage, auf die Sie in Ihrer ursprünglichen Frage Bezug genommen haben, funktioniert möglicherweise in einer WPF-App, in der das App-Modell weniger restriktiv ist, ich kann dies jedoch nicht garantieren. Sie müssen das selbst ausprobieren.

+0

Punkt 1 scheint nicht richtig zu sein: Die erstellte Aufgabe wird auf die Beendigung gewartet, bevor 'd' tatsächlich verwendet wird, daher sollte sie nur null sein, wenn' player.SystemMediaTransportControls' ebenfalls null ist! –

+1

Der Code wie in der Frage wird nicht tatsächlich sogar kompilieren, weil Sie einen Fehler \t CS0165 \t Verwendung von nicht zugewiesenen lokalen Variable 'd''Fehler erhalten. –

+0

Was für eine schöne Erklärung! Ich versuche es nochmal mit diesen Ratschlägen - tut mir leid, dass ich nicht geantwortet habe. Ich dachte, eine Woche Zeit für das Thema könnte meine Gedanken klären. – Hypixus

0

Ich denke, dass Sie hier vielleicht stolpern, gibt es keine Möglichkeit, andere Anwendungen Audio zu steuern. Sie können nur die Transportsteuerelemente verwenden.

Diese Zeile wird die Hintergrund-Task für andere Anwendungen beenden, die Musik wiedergeben und eine neue Instanz erstellen, die Sie verwenden können.

+0

Ich versuche es mit 'SystemMediaTransportControls.GetForCurrentView();', danke. – Hypixus

Verwandte Themen