2016-03-21 17 views
17

Ich habe einen Remote-Dienst, an den externe Anwendungen binden können. Es gibt Situationen, in denen ich die Bindung ablehnen möchte. According to the documentation,Remote-Dienst verweigern Erlaubnis onBind

Den Kommunikationskanal zum Dienst zurücksenden. Kann null zurückgeben, wenn die Clients nicht an den Service binden können.

@Override 
public IBinder onBind(final Intent intent) { 
    return null; 
} 

Rückkehr null in der Tat ein IBinder Objekt nicht zurück und verhindert somit die Verbindung jedoch die anrufende Anwendung erhält nicht richtig diese ‚Information‘.

boolean bound = context.bindService(intent, serviceConnection, flagsHere); 

Ob aus dem Service null oder nicht zurückkehren, gibt diese immer wahr?

According to the documentation,

Returns - Wenn Sie erfolgreich an den Dienst gebunden haben, wahr ist zurückgekehrt; false zurückgegeben wird, wenn die Verbindung nicht hergestellt wird, so dass Sie nicht das Dienstobjekt erhalten

ich angenommen hatte, dass von onBind null Rückkehr bindService false zurück verursacht hätte. Annahmen sind nie eine gute Idee ...

Rückkehr null jedoch die ServiceConnection nicht daran hindern, wird instanziiert aufgerufen, sondern eine Folge wäre keine Option sein, zu überprüfen, ob das Bindemittel in der Tat null in onServiceConnected ist.

Also, meine Frage - Wie "weiß" eine Anwendung, wenn die Bindungsanfrage abgelehnt wurde?

Außerdem, wenn ich auf die Schnelle entscheiden, dass ein Antrag auf onRebind (früher wahr von onUnbind zurückgekehrt) abgelehnt werden sollte, scheine ich nicht in der Lage sein, das Verhalten außer Kraft zu setzen, dies zu verhindern:

@Override 
public void onRebind(final Intent intent) { 

    if (shouldAllowRebind(intent)) { 
     super.onRebind(intent); 
    } else { 
     // ? 
    } 
} 

Ich hoffe, dass jemand etwas Licht für mich werfen kann. Danke im Voraus.

+4

Der Rückgabewert von 'bindService()' war ein Problem für eine ganze Weile. "Wie weiß eine Anwendung, ob die verbindliche Anfrage abgelehnt wurde?"- vermutlich wird seine' ServiceConnection' niemals mit 'onServiceConnected()' aufgerufen. – CommonsWare

+0

Danke @CommonsWare Ich hatte gehofft, dass du diese Frage sehen würdest! Da 'bindService()' true zurückgegeben hat, bleibt die App ' limbo 'erwartet, dass '' ServiceConnection'' onServiceConnected() '' aufruft. Da es (wegen Fehlverhaltens) nicht funktioniert, würden Sie einen Monitor-Thread vorschlagen, der einige Sekunden wartet und dann prüft, ob ein 'boolscher' Bezeichner die Methode signalisiert hat Angenommen, markieren Sie den Kontext als Null verwendet und hoffe GC wird es aufräumen? Ich bin besorgt, dass Android wird glauben, dass die App an den Dienst gebunden ist und es im Speicher halten – brandall

+0

"würden Sie einen Monitor Thread vorschlagen, der ein paar wartet Sekunden und prüft dann, ob eine boolesche Kennung signalisiert hat, dass die Methode aufgerufen wurde? "- persönlich würde ich versuchen, das Gesamtproblem auf eine andere Weise zu lösen (z. B. einzelne API-Aufrufe an den Binder abzulehnen), anstatt die Bindung zurückzuweisen Angesichts dieser Implementierung mentation, etwas zu verwenden, um eine Zeitüberschreitung zu implementieren (z. B. 'postDelayed()' auf einer 'Ansicht'), könnte die beste Option sein. "Anderenfalls markieren Sie den Kontext als Null und hoffen, dass GC ihn aufräumt?" - Entschuldigung, aber ich habe diesen Teil nicht verstanden. – CommonsWare

Antwort

7

Sie müssen wahrscheinlich eine Problemumgehung erstellen. Ich sehe zwei Optionen hier:

  • Geben Sie eine Binder ohne Funktionalität zurück, wenn die Anfrage abgelehnt werden sollte. Der Client muss dann prüfen, ob die gewünschte Funktionalität vorhanden ist.
  • Immer denselben Binder zurücksenden, aber jede Methode einen Exception (z. B. SecurityException) werfen, wenn der Anruf nicht zulässig ist. (Dies wurde auch von @CommonsWare in den Kommentaren vorgeschlagen)
  • Ich würde persönlich bevorzugen den zweiten Ansatz, wie es flexibler ist. (z. B. ermöglicht Per-Call-Erlaubnis/verweigern, löst das Problem der Verweigerung von Sachen nach einer Rebind, etc.)

    +0

    Vielen Dank für Ihre Antwort - könnten Sie in dem Code verweisen, in dem 'bindService den Dienst nicht synchron 'erstellt? Für 'Sind Sie sicher, dass Ihr onServiceConnected nicht aufgerufen wird?' 100% ist Ihnen das nicht passiert? Ich korrigiere die Formulierung in meiner Frage, ich denke, "aufgerufen" wäre eine bessere Terminologie, die "instanziiert"? – brandall

    +0

    Der einfachste Weg, dies zu zeigen, ist, wenn Sie sich den Ursprung des onBind-Aufrufs ansehen: Er kommt von einem Handler. Wie Sie wahrscheinlich wissen, werden Handler hauptsächlich für die asynchrone (Interprozess-) Kommunikation verwendet. http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/app/ActivityThread.java#1391 – F43nd1r

    +0

    Der erste Absatz Ihrer Antwort ist vollständig falsch. Wenn Sie einfache Breakpoints hinzufügen, sehen Sie, dass 'bindService' auf die Antwort von' onBind' wartet und davor 'onStartCommand' aufgerufen wird, unabhängig davon, ob der Service läuft oder nicht. Ich bin mir nicht sicher, was Sie in Ihrem Kommentar meinen - dass das System IPC verwenden wird, um die Antwort von 'onBind' zu kommunizieren? – brandall