NullPointerException + BoundService

  • 13 Antworten
  • Letztes Antwortdatum
B

bandchef

Neues Mitglied
0
Hi Leute!

Ich hab ein Problem mit einer NullPointerException! Hier mal die LogCat:

01-05 05:57:29.436: E/AndroidRuntime(906): Caused by: java.lang.NullPointerException
01-05 05:57:29.436: E/AndroidRuntime(906): at com.example.boundservicekommunikation.MyService$MyBinder.count(MyService.java:37)
01-05 05:57:29.436: E/AndroidRuntime(906): at com.example.boundservicekommunikation.MainActivity.onClickCount(MainActivity.java:65)

Ich hab in meinem Projekt zwei res Dateien mit dem Namen ActivityMain.java und MyService.java.

Hier dazu noch der Code, der in Zeile 37 und 65 steckt:

Code:
MyCallback.countUpdate(counter);
und noch Zeile 65:

Code:
myService.myBinder.count();

Falls ihr mehr Code sehen müsst, dann sagt einfach bescheid!
 
da du abgesehen von der Fehlermeldung quasi nichts gepostet hast, gehe ich mal davon aus das dir nicht ganz klar ist was eine NullPointerException ist.

Es bedeutet das der Objektvariable kein Objekt zugewiesen ist, es also nicht existiert, folglich keine aufrufbaren Methoden und auch keine Variablen besitzt - das macht deinen eigentlichen Aufruf unwichtig - es geht um alles was davor passiert bzw. nicht passiert ist, also die Initialisierung des Service oder des Binders(welcher der beiden auch immer die Exception ausgelöst hat).

mfG Toasty
 
Meine Vermutung:
MyCallback ist null.
Warum ist MyCallback überhaupt groß geschrieben?

Guck halt mal wo (und ob) "MyCallback" definiert wird
 
amfa schrieb:
Meine Vermutung:
MyCallback ist null.

Ich glaube du irrst dich:

Code:
myService.myBinder.count();
wird in
Code:
MyCallback.countUpdate(counter);
aufgerufen.
Von dort geht die Exception aus - daher kann es nicht "MyCallback" sein, weil die Funktion ja ausgeführt wird(bis zu dem Punkt an dem sie durch die NPE crasht).
Ich plädiere weiter auf Service oder Binder.

mfG Toasty
 
Oh, stimmt war gestern wohl schon etwas müde :D
Ok dann nehme ich meine Aussage zurück und behaupte das Gegenteil.

Und warte weiterhin auf mehr Code von bandchef.
Anders wird das hier ja nix. ;)
 
Hi Leute,

erstmal Danke für eure Antworten. Hier nun mehr Code:

Die MainActivity.java:
Code:
package com.example.boundservicekommunikation;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;

import com.example.boundservicekommunikation.MyService.ICallback;
import com.example.boundservicekommunikation.MyService.MyBinder;

public class MainActivity extends Activity implements ICallback
{    
    MyService myService  = new MyService();    //Eine Instanz von MyService
            
    //Eine Service Connection überwacht den Status eines Services
    private ServiceConnection myServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myService.myBinder = (MyBinder) service;
            myService.myBinder.setCallback(MainActivity.this);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };
    
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Den Service binden (binden = Service starten)
        bindService(new Intent(this, MyService.class), myServiceConnection, BIND_AUTO_CREATE);
    }
    
    
    @Override
    protected void onDestroy() {
        unbindService(myServiceConnection);
    }

    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    
    public void countUpdate(int counter) {
        TextView textView = (TextView) findViewById(R.id.textView1);
        textView.setText(String.valueOf(counter));
    }
    
    
    public void onClickCount(View button) {
        myService.myBinder.count();    //inkrementiert counter
    }
}
die MyService.java:

Code:
package com.example.boundservicekommunikation;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

//MyService Klasse
public class MyService extends Service {
    
    MyBinder myBinder = new MyBinder();    //Eine Instanz des Binders
    private ICallback MyCallback;    //Eine Referenz vom Typ ICallback
    private int counter = 0;    //Der Counter
    
    
    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }
    
    
    public interface ICallback {
        public void countUpdate(int counter);
    }
    
    
    //Innere Klasse MyBinder
    public class MyBinder extends Binder {
        void setCallback(ICallback MyCallback)
        {
            MyService.this.MyCallback = MyCallback;
        }
        
        //inkrementiert den counter
        void count() {
            counter++;
            MyCallback.countUpdate(counter);
        }
        
        //counter wird zurückgegeben
        int getCounter() {
            return counter;
        }
    }
}
Was ich an meinem Code nicht verstehe, ist, warum dann nirgends ein Fehler beim kompilieren entsteht, wenn ich Variablen nicht richtig initialisiert hätte? Denn jedes dieser Objekte die ich über den .-Operator ansprechen kann, tauch auch so in diesen Codevorschlägen auf! Kann es auch eventuell an der layout.xml oder dem Manifest liegen?

PS: Die MyCallback ist deklariert; gleich in der 11. Zeile. Ihr habt recht. Das großgeschrieben MyCallback ist irre führend. Ich hab's nun zu myICallback geändert, weil's ja eigentlich eine Variable vom Typ ICallback ist. Allerdings jetzt nicht hier, sonder in meinem Code. Für die Fehlerfindung wisst ihr ja jetzt bescheid.
 
Zuletzt bearbeitet:
Du musst unterscheiden zwischen Fehlern, die der Compiler schon erkennen kann.
z.B.
Wenn du irgendwo nur:
Object object;
definierst aber niemals mehr damit arbeitest ausser irgendwann auf eine Methode zuzugreifen.
Das kann der Compiler erkennen.

Wenn aber z.B. hier:
MyService.this.MyCallback = MyCallback;
MyCallback null wäre, kann der Compilter das nicht erkennen, das sieht man erst zur Laufzeit und dann fliegt auch ein NullPointer.

Du solltest ganz einfachmal mit dem debugger durch dein programm gehen und in der besagten Zeile gucken ob wirklich alles gesetzt ist.

Und dann siehst im Debugger ja, was davon null ist.
 
Code:
myService.myBinder = (MyBinder) service;
irgendwie gefällt mir der Cast nicht...übergeben wird service als IBinder...
Ich bin mir nicht ganz sicher wo das her kommt...also ob es tatsächlich von myBinder stammt
Und ich bin mir auch nicht sicher ob nicht schon das fehlerhafte casten eine Exception rauswerfen würde...
aber nur mal so als Idee, ansonsten würde ich hier passen.

mfG Toasty
 
Du meinst also, dass ich den expliziten Typecast weglassen soll und so service als das "speichern lassen" als das übergeben wurde, nämlich als IBinder?

Code:
myService.myBinder = service;
So sollte es dann aussehen?

Edit: Wenn ich den expliziten Typecast weg lasse, bekomm ich eine Fehlerinfo, dass er nicht von IBiner zu myService.myBinder casten kann...
 
mein Problem ist gerade einfach die Frage wo der service her kommt...wenn du es nicht typecastest kannst du natürlich nicht mit den Funktionen von myBinder arbeiten, genausowenig wie ihn einfach auf einen myBinder zuweisen.

Am besten hältst du dich mal an amfa's Vorschlag:
amfa schrieb:
Du solltest ganz einfachmal mit dem debugger durch dein programm gehen und in der besagten Zeile gucken ob wirklich alles gesetzt ist.

Und dann siehst im Debugger ja, was davon null ist.

mfG Toasty
 
Ok. Debuggen.

Ich bin zwar etwas erfahrener in C++, aber ich programmiere erst seit wenigen Tage/Wochen Android mit Eclipse. Kannst du mir sagen, wie ich im Debugger von Eclipse Schritt vorwärts gehen kann?

Hab das nämlich schon probiert, aber die Buttons für den schrittweisen weitersetzen des InstructionPointers sind immer ausgegraut!

Edit jetzt sehe ich gerade, dass das nicht (mehr) der Fall ist. Jetzt müsste ich aber nur noch wissen, wie ich den Inhalt von Variablen angucken kann; bspw. interessant bei der int counter...

Edit2: Wo finde ich die Taste für "einen Schritt weiter"? Das gibt's doch nicht...

Der ursprüngliche Beitrag von 12:25 Uhr wurde um 13:06 Uhr ergänzt:

Ich musste mir jetzt viele einzelne Breakpoints setzen, damit ich schrittweises Debuggen imitieren konnte.

Aber so wie's aussieht, wirft die Zeile
Code:
myICallback.countUpdate(counter);
in der MyService.java innerhalb der count() Methode die NullPointerException.

Weiter weiß ich aber jetzt dennoch nicht...
 
Zuletzt bearbeitet:
Entweder ist der service an dieser Stelle ein MyBinder oder null.
Alles andere sollte eine ClassCastException werfen.

Aber debuggen wird das einfachste sein um zu sehen was dort nicht gesetzt ist.
 
Danke für die Info. Aber wie ich gestern schon geschrieben habe, hakt es in dieser Zeile:
Code:
myICallback.countUpdate(counter);

Das hab ich durch debuggen rausgefunden. Wenn ich diese Zeile aufrufe, dann springt mir der Debugger NICHT in die MainActivity zurück in der er eigentlich dieses countUpdate ausführen soll!
 
Wenn du mit dem Debugger in der Zeile bist, dann fahr mit der maus über myICallback und guck z.b. ob das null ist.
Wenn du mit der Maus drüber gehst zeigt der dir normalerweise an welchen Wert die Variable hat.

Mit F5 (Step into) kannst du auch in die Methode selber reingehen und gucken ob du da hängen bleibst.

Irgendwas bei dir ist halt null und das musst du rausfinden.
Setz ein Breakpoint in Zeile 65 in der MainActivity und schau dir die variablen an.

Eventuell wenn ich heute abend zeit hab guck ich mir das selbst mal an. dann bräuchte ich aber dein komplettes Eclipse Projekt.
 
Zurück
Oben Unten