CastException bei Service Binder

  • Antworten:13
  • Bentwortet
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 01:00:03 via Website

Hallo Leute... Ich bin hier seit zwei Tagen Am Verzweifeln weil es mir nicht gelingt einen Service über einen Binder mit ner Activity zu verbinden...

Ich hab den notwendigen Code jetzt in ein Testprojekt ausgelagert damit das ganze etwas übersichtlicher ist.
Es ist so das er mir bei dem Versuch meinen Binder zu casten eine Exception wirft.... mir ist nur schleierhaft warum das so ist....

-----Der Service ----
1public class Test_service extends Service{
2
3 public final IBinder mBinder = new TestBinder();
4
5 public class TestBinder extends Binder{
6 public String MACHWAS(){
7 return "WAS";
8 }
9 public boolean Update() {
10 return false;
11 }
12 public boolean Send() {
13 return false;
14 }
15 Test_service getService(){
16 return Test_service.this;
17 }
18 }
19
20
21 @Override
22 public IBinder onBind(Intent intent) {
23 return mBinder;
24 }
25 @Override
26 public void onCreate() {
27 }
28
29 @Override
30 public void onDestroy() {
31 Toast.makeText(this, "Destroy", 5000).show();
32 }
33 @Override
34 public void onStart(Intent intent, int startid) {
35 Toast.makeText(this, "Start", 5000).show();
36 }
37}

Activity---------
1public class Test extends Activity {
2
3
4 /**************************************/
5 private Test_service.TestBinder mbinder;
6 private ServiceConnection CoundownServiceConnection = new ServiceConnection(){
7
8
9 public void onServiceConnected(ComponentName name, IBinder service) {
10 try{
11/*-------->*/ mbinder = (Test_service.TestBinder)service;//<-------Hier wirft er die CastException
12 Toast.makeText(getApplicationContext(), "OK", 10000).show();
13
14 }
15 catch(Exception ex){
16 Toast.makeText(getApplicationContext(), "FAIL", 10000).show();
17 }
18 }
19 public void onServiceDisconnected(ComponentName name) {
20 }
21
22 };
23 /*****************************/
24
25
26
27 @Override
28 public void onCreate(Bundle savedInstanceState) {
29 super.onCreate(savedInstanceState);
30 setContentView(R.layout.main);
31
32
33 final Intent i = new Intent(getApplicationContext(),Test.class);
34 getApplicationContext();
35 bindService(i, CoundownServiceConnection,Context.BIND_AUTO_CREATE);
36
37
38 }
39
40}

manifest----------
1<?xml version="1.0" encoding="utf-8"?>
2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="de.mma"
4 android:versionCode="1"
5 android:versionName="1.0">
6 <uses-sdk android:minSdkVersion="7" />
7
8 <application android:icon="@drawable/icon" android:label="@string/app_name">
9 <activity android:name="Test"
10 android:label="@string/app_name">
11 <intent-filter>
12 <action android:name="android.intent.action.MAIN" />
13 <category android:name="android.intent.category.LAUNCHER" />
14 </intent-filter>
15
16 </activity>
17
18
19 <service android:name="test_service.binder" android:enabled="true" android:exported="false" android:process=":test" />
20 </application>
21</manifest>

Ich hoffe wirklich mir kann einer helfen ich hab da jetzt schon so lang reingeglotzt das ich einfach gar nix mehr sehe.....

Antworten
Felix
  • Forum-Beiträge: 259

17.12.2011, 11:37:05 via Website

Tach!

Hallo Leute... Ich bin hier seit zwei Tagen Am Verzweifeln weil es mir nicht gelingt einen Service über einen Binder mit ner Activity zu verbinden...

Ich hab den notwendigen Code jetzt in ein Testprojekt ausgelagert damit das ganze etwas übersichtlicher ist.

Ich konnte den Fehler nicht nachvollziehen - allerdings musste ich erst das Projekt korrigieren, damit es überhaupt läuft. Mit dem gegebenen Code wurde der Service gar nicht erst gestartet. Mit Services habe ich selbst noch nicht gearbeitet, aber alles notwendige dazu entnahm ich dem Abschnitt Local Service Sample der Service-Dokumentation.

Activity---------
1@Override
2 public void onCreate(Bundle savedInstanceState) {
3 super.onCreate(savedInstanceState);
4 setContentView(R.layout.main);
5
6 final Intent i = new Intent(getApplicationContext(),Test.class);
7 getApplicationContext();
8 bindService(i, CoundownServiceConnection,Context.BIND_AUTO_CREATE);
9 }
10}

Der Intent will nicht die Test.class sondern die vom Service, also Test_service.class. Das einzelne getApplicationContext(); ist nutzlos.

manifest----------
1<service android:name="test_service.binder" android:enabled="true" android:exported="false" android:process=":test" />

Hier muss als android:name der Klassename vom Service angegeben werden, nicht der vom Binder. Groß-/Kleinschreibung ist auch zu beachten.


Felix.

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 11:46:16 via Website

hier noch mal die Methode wo die CastException ausgelöst wird....

1public void onServiceConnected(ComponentName name, IBinder service) {
2 try{
3 mbinder = (Test_service.TestBinder)service; //<-----Hier wirft er die CastException
4 Toast.makeText(getApplicationContext(), "OK", 10000).show();
5
6 }
7 catch(Exception ex){
8 Toast.makeText(getApplicationContext(), "FAIL", 10000).show();
9 }
10 }

Vielleicht habe ich das ganze auch einfach noch nicht so ganz verstanden...
Der Parameter "IBinder service" ist doch der von mir Implementierte Binder in der Service klasse und wird dort von der Methode onBind() geliefert.
Wieso lässt der sich also nicht casten???

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 12:03:28 via Website

Hey Felix Danke für die Antwort
Entschuldige die Fehler sind wohl gestern entstanden als ich das ganze etwas übersichtlicher gestalten wollte um es hier zu posten.
Kommt nicht wieder vor :)
Das eigentliche Projekt enthält diese Fehler nicht.

Also Ich habe hier im Prinzip einen Lauffähigen Service der auch startet nur das Binden Funktioniert eben nicht weil sich der implementierte Binder nicht casten lässt ( mbinder = (Test_service.TestBinder)service )

Ich hab jetzt schon sehr viele Beispiele durchgearbeitet auch die der Doku aber das Casting liefert immer wieder die selbe Exception...
So langsam kommt in mir der Verdacht auf das es eventuell gar nicht am Code liegt nur weis ich nicht sorecht wie ich jetzt damit umgehen soll.


Funktioniert denn dieses Beispiel bei dir.. Also speziell das Binding?

— geändert am 17.12.2011, 12:13:12

Antworten
Felix
  • Forum-Beiträge: 259

17.12.2011, 12:35:12 via Website

Tach!

Also Ich habe hier im Prinzip einen Lauffähigen Service der auch startet nur das Binden Funktioniert eben nicht weil sich der implementierte Binder nicht casten lässt ( mbinder = (Test_service.TestBinder)service )

Ich hab jetzt schon sehr viele Beispiele durchgearbeitet auch die der Doku aber das Casting liefert immer wieder die selbe Exception...
So langsam kommt in mir der Verdacht auf das es eventuell gar nicht am Code liegt nur weis ich nicht sorecht wie ich jetzt damit umgehen soll.

Debugging! Setz einen Breakpoint auf die Zeile und starte im Debug-Modus. Dann schau dir an, was in service wirklich steckt.

Funktioniert denn dieses Beispiel bei dir.. Also speziell das Binding?

Ja, nach den genannten Korrekturen.


Felix.

P.S. Ich denke, die eigentliche Funktionalität des Services gehört nicht in den Binder sondern in die Service-Klasse selbst.

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 12:55:59 via Website

Ich kann nix auffälliges feststellen... Ich hab den Try block mal entfernt um ne Aussage von Logcat zu bekommen...
wie Gesagt ich habe bei dem Projekt die selben Korrekturen gemacht wie du...


12-17 12:50:08.500: ERROR/AndroidRuntime(23663): FATAL EXCEPTION: main
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): java.lang.ClassCastException: android.os.BinderProxy
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at de.mma.Test$1.onServiceConnected(Test.java:22)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1064)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1081)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at android.os.Handler.handleCallback(Handler.java:587)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at android.os.Handler.dispatchMessage(Handler.java:92)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at android.os.Looper.loop(Looper.java:123)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at android.app.ActivityThread.main(ActivityThread.java:3687)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at java.lang.reflect.Method.invokeNative(Native Method)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at java.lang.reflect.Method.invoke(Method.java:507)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
12-17 12:50:08.500: ERROR/AndroidRuntime(23663): at dalvik.system.NativeStart.main(Native Method)

Antworten
Felix
  • Forum-Beiträge: 259

17.12.2011, 13:10:22 via Website

Marcel S.
Ich kann nix auffälliges feststellen... Ich hab den Try block mal entfernt um ne Aussage von Logcat zu bekommen...

Mach mal nicht nur Logcat sondern benutz den Debugger von Eclipse (oder der IDE, die du verwendest). Der Logcat sagt nur, dass der Cast in die Hose geht. Im Debugger kannst du zumindest sehen, was überhaupt in service übergeben wird. Ohne diese Information ist alles weitere nur wie Stochern im Nebel.

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 13:29:50 via Website

Ich bin nicht unbedingt geübt im Umgang mit dem Eclipse Debugger... :(

Ich hab den Breakpoint jetzt auf die Zeile gesetzt wo das Casting stattfinden soll
wie Kann ich mir das ganze Jetzt im Detail ansehen. Bei Visual c++ genügte ein klick...
Oder siehst du in diesen Zeilen bereits irgend etwas ausergewöhnliches ??

Test$1.onServiceConnected(ComponentName, IBinder) line: 22
LoadedApk$ServiceDispatcher.doConnected(ComponentName, IBinder) line: 1064
LoadedApk$ServiceDispatcher$RunConnection.run() line: 1081
ActivityThread$H(Handler).handleCallback(Message) line: 587
ActivityThread$H(Handler).dispatchMessage(Message) line: 92
Looper.loop() line: 123
ActivityThread.main(String[]) line: 3687
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 507
ZygoteInit$MethodAndArgsCaller.run() line: 842
ZygoteInit.main(String[]) line: 600


Vielen Dank schon mal für deine Hilfe :)

Antworten
Felix
  • Forum-Beiträge: 259

17.12.2011, 13:53:04 via Website

Ich bin nicht unbedingt geübt im Umgang mit dem Eclipse Debugger... :(

Das ist eines der wichtigsten Werkzeuge beim Fehlersuchen.

Ich hab den Breakpoint jetzt auf die Zeile gesetzt wo das Casting stattfinden soll
wie Kann ich mir das ganze Jetzt im Detail ansehen. Bei Visual c++ genügte ein klick...

Wenn der Debugger startet und nicht in die Perspektive "Debug" wechselt, kannst du das über Windows->Open Perspective->Debug veranlassen. In der sollte sich ein Fenster "Variables" befinden (oder öffnen über Windows->Show View->Variables). Wenn der Breakpoint erreicht ist, siehst du das im Code-Fenster an der Färbung der Zeile. Jetzt im Variables-Fenster die "service" suchen. Als Value sollte da erstmal "Test_service$TestBinder" stehen und in der Fußzeile des Variables-Fensters nochmal mit Package-Namen. Das ist jedenfalls der Klassenname vom tatsächlich übergebenen Parameter. Wenn da was anderes steht, wird was anderes übergeben. Mit dem, was das dann konkret ist, kann man weitere Vermutungen und Untersuchungen anstellen. (Bei nicht-skalaren Inhalten (Klassen, Arrays) kann man die Variable aufklappen und sieht deren Innenleben.)

Oder siehst du in diesen Zeilen bereits irgend etwas ausergewöhnliches ??

Nein, da sieht man nur die Orte im Aufrufstack, nicht aber, was da jeweils konkret übergeben wurde. Dir nützt das grad nicht weiter, weil die fragliche Stelle ja erreicht wird, nur mit etwas vermutlich falschem im Schlepptau. Über dessen Inhalt schweigt sich aber die Exception aus.

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 14:15:35 via Website

Ok diese Info ist wirklich hilfreich :)




Was mir jetzt auf Anhieb auffällt ist...
Test_service$TestBinder erscheint so schonmal nicht.

Antworten
Felix
  • Forum-Beiträge: 259

17.12.2011, 14:31:22 via Website

Was mir jetzt auf Anhieb auffällt ist... Test_service$TestBinder erscheint so schonmal nicht.

Ja, stattdessen BinderProxy. Das heißt für mich, dass du nicht direkt auf den Binder zugreifen kannst, was vermutlich an einer Prozessgrenze oder ähnlichem scheitert. In dem Fall müsstest du dann dem Abschnitt Remote Messenger Service Sample folgen und über einen Messenger mit deinem Service kommunizieren. Oder aber – und das hatte ich bei mir auch noch entfernt – im Manifest das Attribut android:process rauswerfen. Das sorgt bei mir nachvollziehbar für BinderProxy vs. Test_service$TestBinder.

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 14:31:43 via Website

Ich stell mich grad wahrscheinlich ziemlich dämlich an aber ich seh den Wald vor lauter Bäumen nicht mehr :)
Ich probier das gleich mal aus...

— geändert am 17.12.2011, 14:36:08

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 14:51:25 via Website

Oh man ich bin dir echt dankbar :)

Das Attribut android:process war tatsächlich das Problem... Ich habe das aus einem Beispiel übernommen und nicht weiter drüber nachgedacht :D.

Kannst du mir eventuell noch einen Tip geben wie ich es bewerkstellige das der Service die Activity überlebt???
Im Moment wird er mit der Activity Beendet Allerdings war ich der Annahme das ein Service grundsätzlich weiter läuft wenn er nicht explizit beendet wird.

Antworten
Marcel S.
  • Forum-Beiträge: 120

17.12.2011, 14:59:29 via Website

Die Letzte Frage hat sich glaube ich erledigt... :)

Ich Starte den Service jetzt so

1final Intent i = new Intent(this,Test_service.class);
2 startService(new Intent(this,Test_service.class));
3 bindService(i, CoundownServiceConnection,0);

Nochmals vielen Dank für deine Zeit Ich denke mal man kann das hier als gelöst betrachten :)


vielleicht kannst du bei gelegenheit ja auch bei einem anderen Problem von mir reinschauen :)
Tschüss erst mal.
https://www.nextpit.de/de/android/forum/thread/445717/Problem-beim-Zugriff-auf-Kontaktinformationen

Antworten