NullPointerException

bandchef

Mitglied
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)


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

Java:
MyCallback.countUpdate(counter);

und noch Zeile 65:

Java:
myService.myBinder.count();
 

bandchef

Mitglied
Danke für eure Antworten :) Hier dann mehr code:

Java:
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
	}
}

Java:
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 myICallback;	//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 myICallback)
		{
			MyService.this.myICallback = myICallback;
		}
		
		//inkrementiert den counter
		void count() {
			counter++;
			myICallback.countUpdate(counter);
		}
		
		//counter wird zurückgegeben
		int getCounter() {
			return counter;
		}
	}
}
 

dzim

Top Contributor
Demnach würde ich als Erstes sagen, das im Binder nie #setCallback aufgerufen wird. Dadurch dann in 37 die Exception.

Aus dem Stehgreif heraus liegt das einfach an folgendem: Du erstellst zwar eine Instantz eines Services, das ist aber nicht der, der durch das #bindService erstellt wird, dadurch kennt die echte Instanz natürlich dein CallBack nicht. Ich verwende hier den Ansatz über einen android.os.Messenger.Messenger, der in der ServiceConnection in der #onServiceConnected per
[c]Messenger m = new Messenger(service); // service == der IBinder aus der onServiceConnected-Methode[/c]
gesetzt wird.
Danach kannst du per
Java:
try {
	Message msg = Message.obtain(null, TestService.MSG_REGISTER_CLIENT);
	msg.replyTo = mMessenger;
	mService.send(msg);
} catch (RemoteException e) {
	// In this case the service has crashed before we could even do anything with it
}
einfache Daten zum Service hin senden. Idealerweise speicherst du dir den Messenger in deiner Activity, dann kannst du das auch an anderen Stellen machen...

Im Service hast du dann folgendes:
Java:
	private final ArrayList<Messenger> mClients = new ArrayList<Messenger>();
	private final Messenger mMessenger = new Messenger(new IncomingHandler(this));

	public static final int MSG_REGISTER_CLIENT = 1;
	public static final int MSG_UNREGISTER_CLIENT = 2;

	private static final class IncomingHandler extends Handler {
		
		private TestService testService = null;
		
		public IncomingHandler(TestService testService) {
			this.testService = testService;
		}
		
		@Override
		public void handleMessage(Message msg) {
			
		switch (msg.what) {
		
		case MSG_REGISTER_CLIENT:
			testService.mClients.add(msg.replyTo);
			break;
		
		case MSG_UNREGISTER_CLIENT:
			testService.mClients.remove(msg.replyTo);
			if (testService.mClients.isEmpty()) {
				// cleanup
			}
			break;

		default:
			super.handleMessage(msg);
		}
	}
}

Wichtig ist aber vor dem unbind noch alles zu leeren, also:
Java:
			if (mService != null) { // meine Instanz des Messengers
				try {
					Message msg = Message.obtain(null, TestService.MSG_UNREGISTER_CLIENT);
					msg.replyTo = mMessenger;
					mService.send(msg);
				} catch (RemoteException e) {}
			}
			// Detach our existing connection.
			unbindService(mConnection);

Savvy?
 

Neue Themen


Oben