2010-03-21 27 views
25

Ich habe eine bestimmte Situation: startet ein Dienst von einem Broadcast-Empfänger eine Aktivität gestartet. Ich möchte es ermöglichen, dass diese Aktivität zurück zum Dienst kommuniziert. Ich habe mich entschieden, AIDL zu verwenden, um es zu ermöglichen. Alles scheint funktioniert gut, außer bindService() Methode in onCreate() der Aktivität aufgerufen. bindService() löst tatsächlich eine Nullzeigerausnahme aus, weil onServiceConnected() nie aufgerufen wird, während onBind() Methode des Dienstes ist. Wie auch immer, bindService() gibt True zurück. Der Dienst ist offensichtlich aktiv, weil er die Aktivität startet. Ich weiß, dass das Anrufen einer Aktivität von einem Dienst seltsam klingen kann, aber das ist leider die einzige Möglichkeit, Spracherkennung in einem Dienst zu haben.onServiceConnected nie nach bindService-Methode

Vielen Dank im Voraus

Antwort

13

Ich kann nicht das genaue Problem aus Ihrer Beschreibung bilden, also werde ich hier erraten! Wie kann bindService()NullPointerException werfen? Dies kann (oder sollte) nur passieren, wenn Sie keinen Service oder ServiceConnection Listener bereitstellen.

bindService() kann kein NullPointerExceptionweilonServiceConnected() werfen wird nicht aufgerufen. Der Anruf an onServiceConnected() ist ein Produkt von bindService().

Also ich denke, Sie rufen eine AIDL Methode, bevor die Service tatsächlich verbunden hat?

+1

ja sorry, ich verstehe das Problem könnte besser erklärt werden. NullPointerException wird ausgelöst, da die Remote-Schnittstelle niemals als Remote ausgefüllt wird = IRemoteService.Stub.asInterface (service); in onServiceConnected() wird nie aufgerufen. Sollte bindService den onServiceConnected sofort auslösen? – Matroska

+2

'onServiceConnected()' sollte nicht __ unmittelbar aufgerufen werden, wird es wahrscheinlich eine kleine Verzögerung geben. – MrSnowflake

+0

Sie haben Recht! Die Methode wird nicht sofort aufgerufen. Das war mein Problem. – Matroska

36

Nach Stunden des Versuchens, das herauszufinden, ist das Problem, dass die Beispiele, die die Erstellung des Diensts anzeigen, die onBind-Methode nicht enthalten oder sie den folgenden Beispielcode haben oder es für Sie generiert:

public IBinder onBind(Intent intent) { 
    // TODO Auto-generated method stub 
    return null; 
} 

Dies führt dazu, dass die onServiceConnected-Methode fehlschlägt oder nie tatsächlich ausgeführt wird. Die Lösung ist sehr einfach, das ist die folgende:

public IBinder onBind(Intent intent) { 
    return mBinder; 
} 

Wo Sie zurück ein einfaches Bindemittel, wie die folgende erstellen konnte:

private final IBinder mBinder = new LocalBinder(); 
public class LocalBinder extends Binder { 
    public ConferenceService getService() { 
    return ConferenceService.this; 
    } 
} 
+3

Danke, Brad, rettete mich einige Zeit hier! Ich hatte zwei Probleme, nämlich den, auf den Sie hier hinweisen, und nicht, dass der Dienst in der Manifestdatei definiert ist. Ich fand, dass das Überprüfen des Status von bindService() auch wichtig ist. – DustinB

+0

Dank Brad, spart mir auch eine Menge Zeit – Houcheng

+0

Dies ist hier dokumentiert: http://developer.android.com/guide/components/bound-services.html#Binder – Rolf

37

Ich habe gerade eine andere Version dieses Problem erfahren, mit dem gleichen Symptom von onServiceConnected(...) nicht angerufen werden. Die Ursache war in meinem Fall anders.

Sie müssen sicherstellen, eine Service-Deklaration in Ihrem AndroidManifest.xml innerhalb des Application-Tags zu haben - das war die Wurzel des Problems für mich.

<application android:name=".YourAppTitle" android:icon="@drawable/icon" android:label="@string/app_name"> 
    <activity android:name=".Main" android:label="@string/app_name"> 
    </activity> 
    <service android:name="YourService" /> 
</application> 

Es gibt eine zusätzliche Komplikation, wenn Sie eine separate Android Bibliothek innerhalb von Eclipse verwenden - dem Hinzufügen dieses Service-Tag scheint nur das Problem zu beheben, wenn der referenzierten Dienst im selben Paket wie das Manifest ist; Wenn sich Ihre App im Paket a.b.c befindet und sich AndroidManifest.xml dort befindet, muss "YourService" ebenfalls im Paket a.b.c. enthalten sein. (manuell kopiert von einer anderen Bibliothek, falls notwendig) oder sonst wird der <service..> Tag may/wird ignoriert und onServiceConnected(...) wird immer noch nicht aufgerufen.

Dies war der Fall für mein Projekt, obwohl ich eine geeignete Import-Anweisung für den Service in meinem Code verwendet habe.Eclipse zeigte keinen Fehler, sodass der Import die Klasse aus einer anderen Bibliothek im Eclipse-Arbeitsbereich korrekt identifizierte.

HTH

+0

Mein Dienst befindet sich in einer Bibliothek, und ich habe dieses Problem: Müssen Sie einen neuen Dienst erstellen, der den alten erbt? –

+0

Ich habe ein Bibliotheksprojekt, das einen Abrechnungsdienst enthält, den ich in einer Reihe von untergeordneten Projekten weitgehend identisch halten möchte. Ich habe das geändert, um abstrakt zu sein, und einen Dienst gemacht, der es im Unterprojekt erbt, aber ich bekomme den gleichen Fehler wie vorher. Um klar zu sein, muss der 'bindService (...)' Aufruf von dem geerbten 'Service' stammen oder kann er im abstrakten Elternteil sein? Und kennen Sie die Ursache für dieses Problem? –

+0

Was ich geschrieben habe, sind alle Informationen, die ich habe, fürchte ich; Ich habe die Android-Entwicklung durch Frustration mit den API- und Firmware-Fehlern seit dem letzten Jahr eingestellt. – KomodoDave

8

Eine weitere Sache ist, dass, wenn Sie bindservice Methode innerhalb des oncreate Methode rufen dann die onserviceconnected aufgerufen wird, nachdem die oncreate Verfahren beendet ist.

Alle Referenzen auf die Schnittstellenfunktionen, bevor die oncreate endet (oder bevor onserviceconnected aufgerufen wird) zeigt Nullzeigerausnahme.

+0

Das war genau das Problem, auf das ich stieß, ich rief Bind (... innerhalb onCreate an und hatte keine Ahnung, warum der Dienst IMMER null zurück gab, danke !! – Sauron

+0

Das hat es für mich repariert, danke Ich habe Tage in das geschaut. –

22

Das onServiceConnected Ereignis wurde nie in meiner Anwendung aufgerufen.

Das Problem war, dass ich der Dienstname in meiner Anwendung Manifest definiert hatte:

<service android:name="MyService" android:enabled="true"></service> 

Einmal habe ich es in vollen Klassennamen es funktionierte:

<service android:name="com.example.MyService" android:enabled="true"></service> 

Update: Sie können auch einen relativen Klassennamen verwenden:

<service android:name=".MyService" android:enabled="true"></service> 

Geben Sie den Klassennamen mit seiner vollen com.example.MyServiceClass statt nur MyServiceClass an.

+0

Danke. In meinem Fall ist die Verwendung von "MyService" ausreichend, aber mit der Verrücktheit der Programmierung in Java, denke ich, dass dies eine sicherere (oder sicherste) Option sein könnte, wenn ich einen Dienst implementiere. –

+3

eigentlich müssen Sie in ".MyService" nicht die volle einlegen, außer es ist außerhalb des Pakets. –

+1

Ich verstehe nicht genau warum, aber das ist absolut wahr! Diese Antwort hat nur mein Problem behoben. – codepushr

4

Noch eine andere Ursache für die ursprüngliche Frage möglicherweise, dass der Dienst nicht bereits ausgeführt wird, und Sie übergeben 0 als Flag an BindService. Wie so:

bindService(intent, serviceConnection, 0); 

Wenn das, was Sie suchen wäre:

bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 
1

Es kann eine andere Erklärung dafür sein, nicht eine sehr häufige Situation, aber ich schaffte es in sie zu erhalten und verlieren 2 Stunden löse es.

Also was ich tat war, dass ich das Bündel aus der Absicht, die von der onBind-Methode erhalten wurde, wiederverwenden wollte. Aber ich ging für die faule Version und änderte die Klasse der Absicht. Anscheinend verursacht dies, dass onServiceConnected nicht aufgerufen wird. Wahrscheinlich, weil das System einen Verweis auf die Absicht behält und es beim Aufrufen vonServiceConnected verwendet.

Abschließend ändern Sie nicht die Absicht, die Sie in onBind erhalten.

0

Ich rief Bindung mit einer leeren Absicht - getContext().bindService(new Intent(), mConnection, Context.BIND_AUTO_CREATE). Ich muss die Absicht konkretisieren, um anzugeben, an welchen Dienst ich mich binden möchte. Dies ist offensichtlich ein Codefehler, aber die Logcat-Ausgabe war leider nicht klar genug.