Ich habe ein Setup, das ungefähr so aussieht:
class MyFragment implements SomeEventListener {
Application mAppContext;
boolean mBound;
boolean mDidCallUnbind;
MyIBinder mBinder;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBound = true;
mBinder = (MyIBinder) service;
mBinder.getThings();...
}
@Override
public void onServiceDisconnected(ComponentName name) {
mDidCallUnbind = false;
mBound = false;
mBinder = null;
}
};
...
@Override
public void onSomeEvent() {
mAppContext.bindService(...);
}
void unbindService() {
if (mBound && !mDidCallUnbind) {
mDidCallUnbind = true;
mAppContext.unbindService(mConnection);
}
}
@Override
public void onPause() {
unbindService();
super.onPause();
}
}
Von Zeit zu Zeit sehe ich jedoch immer noch den Fehler im Titel: Java.lang.IllegalArgumentException: Service not registered
Wird generiert, wenn unbindService()
aufgerufen wird. Fehlt mir etwas Dummes oder ist noch mehr los? Ich möchte darauf hinweisen, dass möglicherweise mehr als ein Fragment desselben vorhanden ist.
Bearbeiten
Da anscheinend niemand den Code liest, lass es mich erklären. unbindService()
ruft Context.unbindService(ServiceConnection)
nur auf, wenn der Dienst gebunden ist (mBound
) nd zuvor nicht vor der onServiceDisconnected(...)
Rückruf wurde von einem möglichen vorherigen Aufruf von unbindService()
getroffen.
In Anbetracht dessen, gibt es Fälle, in denen Android) Ihren Dienst für Sie aufhebt, sodass der Dienst nicht mehr gebunden wird, aber onServiceDisconnected nicht aufgerufen wird, wodurch ich in einem abgestandenen Zustand bin?
Außerdem verwende ich meinen Anwendungskontext, um die anfängliche Bindung durchzuführen. Angenommen, etwas wie:
@Override
public void onCreate() {
mApplication = getContext().getApplicationContext();
}
Mir ist klar, dass diese Frage bereits beantwortet wurde. Aber ich denke, es gibt Gründe, warum die Leute diesen Fehler machen.
Das Problem liegt wirklich in den Schulungsunterlagen. http://developer.Android.com/reference/Android/app/Service.html zeigt eine korrekte Implementierung während https://developer.Android.com/guide/components/bound) -services.html im 'ActivityMessenger' zeigt eine sehr [~ # ~] falsche [~ # ~] Implementierung.
Im 'ActivityMessenger'-Beispiel könnte onStop () möglicherweise aufgerufen werden, bevor der Dienst tatsächlich gebunden wurde.
Der Grund für diese Verwirrung ist, dass sie den Booleschen Wert für gebundenen Service verwenden, um in verschiedenen Beispielen unterschiedliche Bedeutungen zu haben. (hauptsächlich wurde bindService () OR ist der Dienst tatsächlich verbunden) genannt
In den richtigen Beispielen, in denen die Aufhebung der Bindung () basierend auf dem Wert des gebundenen Booleschen Werts erfolgt, gibt der gebundene Boolesche Wert an, dass der bindService () aufgerufen wurde. Da es für die Ausführung des Hauptthreads in der Warteschlange steht, muss unbindService () aufgerufen werden (damit es ausgeführt werden kann), unabhängig davon, wann (falls überhaupt) onServiceConnected () ausgeführt wird.
In anderen Beispielen, wie in http://developer.Android.com/reference/Android/app/Service.html . Die Bindung gibt an, dass die Dienste tatsächlich gebunden sind, sodass Sie sie verwenden und keine NullPointerException abrufen können. Beachten Sie, dass in diesem Beispiel der Aufruf von unbindService () weiterhin ausgeführt wird und der gebundene Boolesche Wert nicht bestimmt, ob die Bindung aufgehoben werden soll oder nicht .
Verwenden Sie mIsBound
in doBindService()
und doUnbindService()
anstatt in der Instanz ServiceConnection
.
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = (MyIBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBinder = null;
}
};
...
public void doBindService() {
bindService(new Intent(this, MyService.class),
mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
public void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
Dies geschieht in http://developer.Android.com/reference/Android/app/Service.html
Java.lang.IllegalArgumentException: Service not registered
Bedeutet, dass Sie nicht an den Dienst gebunden waren, als unbindService()
aufgerufen wurde.
In Ihrem Fall wurde onSomeEvent()
nie vor dem Aufruf von unbindService()
in onPause()
aufgerufen.
Ein weiterer möglicher Grund für diese Ausnahme könnte sein, dass unbindService
vom falschen Context
aufgerufen wird. Da Dienste nicht nur an Aktivitäten gebunden sein können, sondern auch an andere Instanzen, die von Context
(mit Ausnahme von BroadcastReceivers) geerbt wurden, und zwar auch von anderen Diensten, müssen Sie sicherstellen, dass unbindService
vom Kontext aufgerufen wird das hat den Service
und nicht durch den gebundenen Service
selbst gebunden. Dies würde direkt zu der obigen Ausnahme "Dienst nicht registriert" führen.
Wenn in Ihrer Aktivität unbindService () vor bindService () aufgerufen wird, erhalten Sie dieses IllegalArgumentException
.
Wie vermeide ich es?
Es ist einfach. Sie würden kein Boolesches Flag benötigen, wenn Sie den Dienst in dieser Reihenfolge binden und entbinden.
Lösung 1:
Binden Sie in
onStart()
und lösen Sie inonStop()
Your Activity {
@Override
public void onStart()
{
super.onStart();
bindService(intent, mConnection , Context.BIND_AUTO_CREATE);
}
@Override
public void onStop()
{
super.onStop();
unbindService(mConnection);
}
}
Lösung 2:
InonCreate()
binden und inonDestroy()
binden
Your Activity {
@Override
public void onCreate(Bindle sis)
{
super.onCreate(sis);
....
bindService(intent, mConnection , Context.BIND_AUTO_CREATE);
}
@Override
public void onDestroy()
{
super.onDestroy();
unbindService(mConnection);
}
}
Android offizielle Dokumentation schlägt vor das
Wenn Sie mit dem Dienst nur interagieren müssen, während Ihre Aktivität sichtbar ist , wählen Sie Lösung1 .
Wenn Sie möchten, dass Ihre Aktivität auch im angehaltenen Hintergrund Antworten erhält, wählen Sie ) Lösung2 .
Ich habe genau das gleiche Problem mit meiner Bewerbung. Hin und wieder bekomme ich IllegalArgumentException
. Ich vermute, der Sonderfall liegt vor, wenn der Dienst nicht gebunden ist und onPause
voronServiceDisconnected
heißt. Also würde ich Synchronized
Dinge versuchen, um die korrekte Ausführung sicherzustellen.