6

Ok, jestem nowy w rozwoju Androida i próbuję powiązać usługę, aby móc wywoływać metody w usłudze po jej uruchomieniu. Opisane poniżej działanie i usługa są częścią tej samej aplikacji, więc nie powinno być żadnych problemów, ale za każdym razem, gdy uruchomię swoją aplikację, pojawia się następujący błąd:Wyjątek Android ClassCast podczas wiązania z usługą

java.lang.ClassCastException: android.os.BinderProxy

linia ta dzieje się na to:

LocalBinder binder = (LocalBinder) service; 

Mój kod aktywny (uproszczony jest):

public class Main extends Activity { 

    boolean gpsBound = false; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
    } 

    /** Called whenever the activity is started. */ 
    @Override 
    protected void onStart() { 
     super.onStart(); 
     // Bind to GPSService 
     Intent i = new Intent(this, GPSService.class); 
    startService(i); 
    bindService(i, connection, Context.BIND_AUTO_CREATE); 
    } 

    /** service binding */ 
    private ServiceConnection connection = new ServiceConnection() { 

     public void onServiceConnected(ComponentName className, IBinder service) { 
      // After binding to GPSService get the instance of it returned by IBinder 
     LocalBinder binder = (LocalBinder) service; 
      gpsBound = true; 
     } 

     public void onServiceDisconnected(ComponentName className) { 
      gpsBound = false; 
     } 
    }; 

} 

Usługa:

public class GPSService extends Service { 

    @Override 
    public void onCreate() { 
      super.onCreate(); 
    } 

    @Override 
    public IBinder onBind(Intent i) { 
    // TODO Auto-generated method stub 
    return new LocalBinder<GPSService>(this); 
    } 


    /** 
    * Our implementation of LocationListener that handles updates given to us 
    * by the LocationManager. 
    */ 
    public class CustomLocationListener implements LocationListener { 

     DBHelper db; 

     CustomLocationListener() { 
      super(); 
     } 

    // Overridden methods here... 

    } 

} 

I wreszcie moja LocalBinder:

/** 
* A generic implementation of Binder to be used for local services 
* @author Geoff Bruckner 12th December 2009 
* 
* @param <S> The type of the service being bound 
*/ 

public class LocalBinder<S> extends Binder { 
    private String TAG = "LocalGPSBinder"; 
    private WeakReference<S> mService; 


    public LocalBinder(S service){ 
     mService = new WeakReference<S>(service); 
    } 


    public S getService() { 
     return mService.get(); 
    } 
} 

rozumiem rozumieniu wyjątku ClassCast ale nie mogę zrozumieć, co robić! Podążyłem za przykładem w dokumentacji Google, ale nadal nie działa. Czy ktoś może rzucić jakiekolwiek światło na to, co może być przyczyną tego?

Z góry dziękuję!

Odpowiedz

3

przekazana przez LocalBinder onServiceConnected ma ogólny typ argumentu, podczas gdy zmienna lokalna LocalBinder binder nie ma takiej.

rozwiązać ten czy inny sposób, albo poprzez usunięcie ogólny typ z definicji LocalBinder lub dodając jeden do deklaracji lokalnego spoiwa zmiennej w onServiceConnected

class MyBoundService extends Service{ 
    private final IBinder mBinder = new MyBinder(); 

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

    public class MyBinder extends Binder{ 

     public void doStuff(){ 
      //Stuff 
     } 
     //More Binder Methods 
    } 
} 

class MyActivity extends Activity{ 
    private MyBinder mBinder; 

    @Override 
    protected void onStart(){ 
     Intent intent = new Intent(this, MyBoundService.class); 
     bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
    } 

    @Override 
    protected void onStop(){ 
     unbindService(mConnection); 
    } 

    private ServiceConnection mConnection = new ServiceConnection() { 

     @Override 
     public void onServiceConnected(ComponentName className, IBinder service) { 
      mBinder = (TaskBinder) service; 
      mBound = true; 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName arg0) { 
      mBound = false; 
     } 
    }; 

    private void doStuff(){ 
     if (mBound) 
      mBinder.doStuff(); 
    } 
} 

żadnej realnej potrzeby Fiddle wokół ze słabymi odniesieniami i czymkolwiek. tylko pamiętaj, aby odłączyć (nie ma w próbce)

Jeśli chcesz wywołać metody serwisowe JAK NAJSZYBCIEJ, po prostu wywołaj połączenia onServiceConnected, po ustawieniu mBinder. w przeciwnym razie wystarczy wywołać z innych wywołań zwrotnych (zdarzenia onClick i inne).

+0

Czy oznacza podoba: „LocalBinder spoiwo = (LocalBinder ) Usługi;” Jeśli tak, to nadal daje ten sam błąd! –

+0

Byłem skłonny do całkowitego usunięcia generyków. Będę edytować w krótkim przykładzie użycia usługi boundService, którą teraz piszę. –

+0

Będzie można samemu przejść bez generycznych, ale jeśli mógłbyś podać przykład, który byłby świetny!Dzięki, James –

3

Jeśli próbujesz powiązać usługę lokalną niż tak, możesz po prostu ją rzucić. Jednak jeśli próbujesz powiązać się z usługą zdalnego (oddzielnego procesu), musisz użyć metody AIDL zgodnie z zaleceniami w tym artykule.

http://developer.android.com/guide/components/aidl.html

+0

link nie jest już ważny. –

+0

Oto nowy poprawny link http://developer.android.com/guide/components/aidl.html – MrMaffen

32

atrybut Delete process w AndroidManifest.xml swojej służby.

+2

To jest właściwa odpowiedź. – Snicolas

+1

Ciekawy, szczegółowy powód? –

+0

@ThomasDecaux Sądzę, że LocalBinder może być używany tylko wtedy, gdy usługa działa w tym samym procesie (lokalnym) co aplikacja. Atrybut procesu tworzy oddzielny proces, w którym usługa ma zostać uruchomiona, a zatem do komunikowania się z nią należy używać IPC. Podczas procesu wiązania system Android udostępnia BinderProxy, który działa jako pomost do usługi, dzięki czemu można tworzyć instancje klas IPC (napisane w AIDL). http://stackoverflow.com/a/10610463/269876 –

4

Wystąpił ten sam błąd. Dodałem atrybut android: process = "process_description" w manifeście. Gdy go dodać, usługa jest tworzona jako oddzielny proces, a tym samym uzyskać instancję binderProxy (stąd wyjątkiem klasy cast)

Powiązane problemy