2015-12-14 7 views
5

Meine App ist im Wesentlichen ein Hintergrunddienst, der gelegentlich einen NSD Dienst (Bonjour-Dienst) registrieren muss, um die Erkennung eines vom Hauptserver ausgeführten Socketservers zu ermöglichen Hintergrund-Service (aka von der App laufen).Android: Beenden eines Bonjour-Diensts, der ausgeführt wird, nachdem der Elternprozess abgebrochen wurde

Wenn ich die Android Bonjour Service doc richtig lese, ist dies, wie Sie die Bonjour Service (abgekürzt für Prägnanz) starten:

mNsdManager = Context.getSystemService(Context.NSD_SERVICE); 
mDiscoveryListener = new NsdManager.DiscoveryListener() 
mNsdManager.discoverServices(
     SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); 

... und das ist, wie man es stoppen:

mNsdManager.unregisterService(mRegistrationListener); 

Hier ist der Teil, den ich nicht umschließen kann: wenn der Hauptdienst abrupt abbricht, läuft jeder zum Zeitpunkt des Absturzes registrierte Dienst Bonjour weiter, obwohl er keinen Zweck mehr hat (der Socket-Server hilft Disco) ver steht nicht mehr herum).

Ich kann nicht Ereignis die Zombie Bonjour Dienste bereinigen, wenn der Hauptdienst neu gestartet wird, weil die mRegistrationListener der Dienst anfänglich registriert wurde mit ist auch nicht mehr um.

Ich vermute, dass ich den falschen Ansatz nehme: Wie stelle ich sicher, dass ich nicht ein Durcheinander von Zombies hinterlassen Bonjour Dienstleistungen hinter dem Hauptdienst abgestürzt?

Antwort

1

Unspezifische auf Android Bonjour, könnten Sie versuchen, den Absturz zu handhaben, indem Sie Ihre Service-Einrichtung, wie hier in der Antwort skizziert: Can I call a method before my application go to crash

Wenn Sie dies nicht einstellen können, um den unregisterService Anruf zu tätigen, Sie sollten es einrichten können, um die API des ActivityManagers killBackgroundProcesses zu verwenden. Dies erfordert die Erlaubnis zu Ihrem Manifest hinzufügen:

android.permission.KILL_BACKGROUND_PROCESSES 
+0

Danke, das Abfangen von nicht abgefangenen Exceptions mit 'UncaughtExceptionHandler' ist wahrscheinlich der Weg - obwohl ich auf eine Möglichkeit hoffte, den Bonjour-Dienst innerhalb des Hauptprozesses auszuführen (Ich finde es überraschend, dass die Android-Implementierung diese Option nicht zulässt) . Ich werde Ihre Antwort akzeptieren, wenn in den nächsten Tagen nichts Besseres zustande kommt. – Hugo

+0

Ich stimme zu, Sie würden denken, es gibt einen richtigen Weg, damit umzugehen. Ich konnte keine Dokumentation finden, um die Theorie zu unterstützen, aber es kann vom Betriebssystem gehandhabt werden. Es kann sein, dass Google denkt, dass die Leute nicht denken, es überhaupt zu tun, also sollten sie automatisch damit umgehen! –

+0

Danke @ Thril, mit dem 'UncaughtExceptionHandler', um die Registrierung für den Dienst für mich funktioniert (Ich habe erfolgreich getestet durch Absturz des Dienstes ein paar Sekunden nach der Registrierung des Dienstes mit einem Daemon-Timer in einem separaten Thread) – Hugo

2

Wenn ich Sie richtig verstanden, die Hauptleistung (der mit dem Server-Socket) Register/deregistriert einen Nsd Dienst, während ein Hintergrunddienst startet/stoppt Entdeckung der Nsd Service. Ich denke, das ist was du tust, also ist deine "Annäherung" korrekt.

In Bezug auf das Problem, ich möchte Sie auf Android Nsd begrüßen. Es gibt eine Menge von bugs mit dem Framework (unter denen Sie Ihr Problem finden können), dass ab Android 6.0 noch nicht behoben wurden, so dass Entwickler andere Frameworks stattdessen verwenden.

Kommen wir zurück zu der Frage, könnte man UncaughtExceptionHandler versuchen, nur im Kopf behalten, dass alle Rückrufe asynchron vom System aufgerufen werden, und Sie können NPE erhalten, wenn es mRegistrationListener.onServiceUnregistered() nennt, weil, wie Sie gesagt haben, „es ist nicht mehr um ".

In Bezug auf die Service Bereinigung, ist es theoretisch möglich, aber nur nach NsdManager Quellcode Anpassung (Zugriffsmodifikator von einigen Methoden benötigt werden, um geändert zu erreichen und dann austragen mRegistrationListener von einem anderen Prozess, es zu löschen führen würde von einer Zuhörerkarte von NsdManager). Aber es macht keinen Sinn, wenn die App auf dem Markt veröffentlicht wird.

Es gibt eine weitere Problemumgehung, mit der Sie experimentieren könnten. Wenn ich mich richtig erinnere (möglicherweise falsch), findet die notwendige Bereinigung statt, wenn Nsd deaktiviert wird.Ich habe versucht, es über adb:

// Disable 
adb shell service call servicediscovery 2 
// Enable 
adb shell service call servicediscovery 2 i32 1 

weisen jedoch darauf hin, dass diese Anrufe machen programmatisch nicht trivial sein und höchstwahrscheinlich benötigen Wurzel, die wiederum das Publikum Ihrer Anwendung einschränkt.

In Bezug auf die von @ Thril vorgeschlagene Methode killBackgroundProcesses() wird eine Zeichenfolge mit dem Paketnamen der Anwendung als Parameter verwendet. Aber servicediscovery ist keine App, es ist ein Systemdienst. Sie könnten auch versuchen, den Prozess zur Laufzeit zu beenden (obwohl ich nicht weiß, welcher)), aber seien Sie vorsichtig, sollten Sie untersuchen, welchen Effekt es auf das System bringt und sicher sein, dass der Dienst bei Bedarf automatisch gestartet wird per System oder manuell). Um diese Wurzel zu machen, ist es notwendig.

Zusammenfassend die Antwort, bevor Sie mit Nsd fortfahren, empfehle ich dringend, eine Suche in Bezug auf seine Funktionalität/Bugs zu tun, um mögliche Verschwendung von Zeit und Aufwand zu vermeiden. Einige Referenzen zusätzlich zu den darin enthaltenen Link oben:

  1. NSD Device Lost Message Not Received on Disabling Wifi
  2. NsdManager doesn't stop service discovery

P. S. Persönlich habe ich, nachdem ich mit mehreren Nsd Framework Bugs zu kämpfen hatte, mein eigenes Framework geschrieben.

+0

Dank @Onik, schließlich Die Verwendung des 'UncaughtExceptionHandler' funktionierte wie geplant, ich habe erfolgreich getestet, indem ich den Hauptdienst aus einem separaten Thread mit einem Daemon-Timer abstürzte (' Timer timer = neuer Timer (true); timer.schedule (new SimulateUncaughtException(), 2000); ') – Hugo

+0

Sehr gut @Hugo, Handhabung 'Nsd' Arbeit in einem separaten Thread ist eine gute Idee, - klar haben Sie Zeit, die Registrierung in diesem Fall zu registrieren. Obwohl, ich empfehle immer noch, alle 'Nsd' Callbacks zu überprüfen, vor allem, wenn 'Wifi' (' Ethernet') aktiviert/deaktiviert wird ... – Onik

Verwandte Themen