2016-03-21 13 views
17

Mam usługę zdalną, z którą zewnętrzne aplikacje mogą się wiązać. Są sytuacje, w których mogę chcieć odrzucić zobowiązanie. According to the documentation,Usługa zdalnej odmowy pozwolenia na żądanie

Powrót kanału komunikacji do usługi. Może zwrócić wartość null, jeśli klienci nie mogą powiązać usługi.

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

Wracając zerowy rzeczywiście nie zwracają obiekt IBinder i dlatego uniemożliwia połączenie, jednak aplikacja wywołująca nie poprawnie odbierać tę „informacje”.

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

Czy wraca do wartości zerowej, czy nie z usługi, zawsze zwraca wartość true?

According to the documentation,

Powroty - Jeśli pomyślnie związany z usługą, prawdą jest zwrócone; false jest zwracana, jeżeli połączenie nie jest wykonany tak będzie nie odbierać obiekt serwisowy

Przypuszczałem, że powrót zerowy od onBind spowodowałby bindService do return false. Założenia nie są dobrym pomysłem ...

Wracając zerowa ma jednak zapobiec ServiceConnection od bycia instancja wywoływany, ale konsekwencją tego byłoby rozwiązaniem, aby sprawdzić, czy spoiwo jest w rzeczywistości wartość null w onServiceConnected.

Moje pytanie - W jaki sposób aplikacja "wie", czy żądanie powiązania zostało odrzucone?

Dodatkowo, jeśli zdecyduję się na bieżąco, że wniosek do onRebind (uprzednio zwracanej prawda od onUnbind) powinna zostać odrzucona, wydaje mi się być w stanie zastąpić zachowanie, aby zapobiec w ten sposób:

@Override 
public void onRebind(final Intent intent) { 

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

Mam nadzieję, że ktoś może rzucić trochę światła dla mnie. Z góry dziękuję.

+4

Wartość zwracana z 'bindService()' była problemem od dłuższego czasu. "W jaki sposób aplikacja" wie ", jeśli żądanie powiązania zostało odrzucone?"- prawdopodobnie jego" ServiceConnection "nigdy nie zostanie wywołany z' onServiceConnected() '. – CommonsWare

+0

Dzięki @CommonsWare Miałem nadzieję, że zauważysz to pytanie! Ponieważ' bindService() 'zwrócił true, aplikacja pozostanie w ' limbo "oczekujące, że' ServiceConnection' zadzwoni na 'onServiceConnected()' Jak tego nie robi (z powodu niewłaściwego zachowania), czy sugerowałbyś wątek monitora, który czeka kilka sekund, a następnie sprawdza, czy identyfikator 'boolean' zasygnalizował, że metoda była W przeciwnym razie zaznacz kontekst używany jako zerowy i mam nadzieję, że GC go uporządkuje? Obawiam się, że Android uwierzy, że aplikacja jest związana z Usługą i przechowuje ją w pamięci – brandall

+0

"czy zaproponowałbyś wątek monitorowania, który czeka kilka sekundy, a następnie sprawdza, czy identyfikator boolowski zasygnalizował wywołanie metody? "- osobiście, chciałbym spróbować rozwiązać ogólny problem w jakiś inny sposób (np. odrzucając pojedyncze wywołania API do segregatora) zamiast próbować odrzucić wiązanie Biorąc pod uwagę ten przykład mentacja, użycie czegoś do implementacji limitu czasu (np. 'postDelayed()' na 'widoku') może być najlepszą opcją. "W przeciwnym razie, zaznacz kontekst użyty jako zerowy i mam nadzieję, że GC go uporządkuje?" - Przepraszam, ale nie zrozumiałem tej części. – CommonsWare

Odpowiedz

7

Prawdopodobnie musisz utworzyć obejście. Widzę dwie opcje tutaj:

  • Zwrócić Binder bez żadnych funkcji, jeśli żądanie powinno zostać odrzucone. Klient musi wtedy sprawdzić, czy istnieje pożądana funkcjonalność.
  • Zawsze zwracaj tę samą wartość Binder, ale pozwól każdej metodzie wyrzucić Exception (np. SecurityException), jeśli wywołanie nie jest dozwolone. (Zostało to również zasugerowane przez @CommonsWare w komentarzach)

Osobiste preferuję drugie podejście, ponieważ jest bardziej elastyczne. (np. zezwala na zezwolenie na per-call/deny, rozwiązuje problem odmawiania rzeczy po ponownym powiązaniu, itp.)

+0

Dziękuję za odpowiedź - czy mógłbyś odwołać się do kodu, w którym 'bindService nie tworzy usługi synchronicznie? Dla 'Czy jesteś pewien, że twoja usługa onServiceConnected nie jest wywoływana?' 100% czy to się nie stało? Poprawię sformułowanie w moim pytaniu, myślę, że "wywoływany" byłby lepszą terminologią, która "instancja"? – brandall

+0

Najprościej to pokazać, jeśli spojrzysz na pochodzenie wywołania onBind: pochodzi ono z Handler'a. Jak zapewne wiesz Handlery są najczęściej używane do komunikacji asyncronicznej (międzyprocesowej). http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/app/ActivityThread.java#1391 – F43nd1r

+0

Pierwszy akapit odpowiedzi jest całkowicie błędny. Jeśli dodasz proste punkty przerwania, zobaczysz, że 'bindService' czeka na odpowiedź' onBind', a przed tym 'onStartCommand' jest wywoływana niezależnie od tego, czy usługa była uruchomiona czy nie. Nie jestem pewien, co masz na myśli w swoim komentarzu - Że system użyje IPC do przekazania odpowiedzi 'onBind'? – brandall

Powiązane problemy