# PreferenceListener, aber wie?



## Gast2 (8. Jan 2013)

Hallo Leute,

ich möchte in einer Activity eine Meldung bekommen, wenn in einer anderen eine Preference gesetzt wird. Leider gelingt mir dies nicht und ich weiß nicht warum.
Zum Testen und Veranschaulichen habe ich zwei Activitys geschrieben, die ich hier abbilden will.

StartActivity: (das Layout enthält einen Button "Start")

```
package de.praeferenzentest;

import java.util.prefs.PreferenceChangeEvent;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.preference.Preference;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class StartActivity extends Activity implements OnClickListener, OnPreferenceChangeListener {
	private Button btn_start;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.start_layout);

		btn_start = (Button) findViewById(R.id.btn_go);
		btn_start.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		Intent intent = new Intent(this, ZweiteActivity.class);
		startActivity(intent);
	}

	public void preferenceChange(PreferenceChangeEvent pce) {
		final ToneGenerator tg = new ToneGenerator(
				AudioManager.STREAM_NOTIFICATION, 100);
		tg.startTone(ToneGenerator.TONE_PROP_BEEP);
	}

	public boolean onPreferenceChange(Preference preference, Object newValue) {
		final ToneGenerator tg = new ToneGenerator(
				AudioManager.STREAM_NOTIFICATION, 100);
		tg.startTone(ToneGenerator.TONE_PROP_BEEP);
		return false;
	}

	public boolean onPreferenceClick(Preference preference) {
		final ToneGenerator tg = new ToneGenerator(
				AudioManager.STREAM_NOTIFICATION, 100);
		tg.startTone(ToneGenerator.TONE_PROP_BEEP);
		return false;
	}

	public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {
		final ToneGenerator tg = new ToneGenerator(
				AudioManager.STREAM_NOTIFICATION, 100);
		tg.startTone(ToneGenerator.TONE_PROP_BEEP);
	}
}
```

ZweiteActivity: (das Layout enthält einen Button Save Preference")

```
package de.praeferenzentest;

import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ZweiteActivity extends Activity implements OnClickListener {

	private int value;
	private Button btn_save_preference;
	private SharedPreferences sharedPreferences;
	private Editor editor;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.layout_zweite);

		sharedPreferences = getSharedPreferences("SharedValues", 0);		
		btn_save_preference = (Button) findViewById(R.id.btn_setPreference);
		btn_save_preference.setOnClickListener(this);
		value = 10;
	}

	@Override
	public void onClick(View arg0) {
		editor = sharedPreferences.edit();
		editor.putInt("value", value);
		editor.commit();
	}
}
```

Leider gibt es beim setzen der Preference keinen Beep.
Warum funktioniert keiner der Listener?
Hat jemand eine Lösung?

Frank


----------



## fastjack (8. Jan 2013)

Der Listener muß ja auch irgendwo angeschlossen werden, z.B. mit preference.setOnPreferenceChangeListener


----------



## Gast2 (8. Jan 2013)

mh,...
habe einiges versucht, leider hat es nicht geklappt.
z.B.

```
private Preference preference;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.start_layout);

		btn_start = (Button) findViewById(R.id.btn_go);
		btn_start.setOnClickListener(this);
		
		preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
			
			@Override
			public boolean onPreferenceChange(Preference preference, Object newValue) {
	    		final ToneGenerator tg = new ToneGenerator(
	    				AudioManager.STREAM_NOTIFICATION, 100);
	    		tg.startTone(ToneGenerator.TONE_PROP_BEEP);
				return false;
			}
		});		
	}
```

oder einfach:

```
private Preference preference;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.start_layout);

		btn_start = (Button) findViewById(R.id.btn_go);
		btn_start.setOnClickListener(this);
		
		preference.setOnPreferenceChangeListener(this);
	}
```
wirft beides eine NPE. ???:L

Ich gehe mal davon aus, dass ich den Listener in der StartActivity setzen muss?!
@fastjack: Hattest Du das so gedacht? 
Was mache ich falsch?
(Sorry, bin Anfänger) :rtfm:


----------



## schlingel (9. Jan 2013)

Wo wirft es eine NPE? Der Klassiker vielleicht, View wird nicht gefunden?


----------



## Gast2 (9. Jan 2013)

schlingel hat gesagt.:


> Wo wirft es eine NPE? Der Klassiker vielleicht, View wird nicht gefunden?



Die NPE kommt aus

```
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                final ToneGenerator tg = new ToneGenerator(
                        AudioManager.STREAM_NOTIFICATION, 100);
                tg.startTone(ToneGenerator.TONE_PROP_BEEP);
                return false;
            }
        });
```
bzw.

```
preference.setOnPreferenceChangeListener(this);
```

Wenn ich dies auskommentiere, dann funktioniert der Rest (zB. die View).
Nur eben nicht der PreferenceListener. 

Falls jemand selber basteln möchte,
hier meine Testversion wie oben beschrieben; komplettes Package: 
http://mehlhop.com/data/PraeferenzenTest.zip

hier die LogCat-Meldungen:
http://mehlhop.com/data/log.txt


----------



## schlingel (9. Jan 2013)

Du initialisierst preference auch nicht.


----------



## Gast2 (9. Jan 2013)

schlingel hat gesagt.:


> Du initialisierst preference auch nicht.



stimmt. Aber jetzt...

```
@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.start_layout);

		btn_start = (Button) findViewById(R.id.btn_go);
		btn_start.setOnClickListener(this);
		
		preference = new Preference(this);		
		preference.setOnPreferenceChangeListener(this);
	}
```
Der Konstruktor fordert mindestens einen Parameter: das Object _Context_
Ich gehe davon aus, dass es sich um das Objekt der eigenen Klasse handelt und habe _this _übergeben.

Die NPE ist wech. 

*Aber in*

```
public boolean onPreferenceChange(Preference preference, Object newValue) {
		final ToneGenerator tg = new ToneGenerator(
				AudioManager.STREAM_NOTIFICATION, 100);
		tg.startTone(ToneGenerator.TONE_PROP_BEEP);
		return false;
	}
```
*piepst es immer noch nicht, wenn ich eine Änderung der SharedPreferences vornehme.* ???:L

Ansonsten fällt mir auf, dass ich obwohl ich das Interface _OnPreferenceChangeListener _implementiere die zugehörige Methode _onPreferenceChange _keine _@Override_ - Notation hat. Das ist ungewohnt.


----------



## schlingel (9. Jan 2013)

Warum verwendest du den Konstruktor vom Preference anstatt getSharedPreferences vom Context-Objekt? Ich glaub das Problem ist einfach, dass du mit dem new ein neues Objekt erzeugst was nichts mit den SharedPreferences zu tun hat, die du dann veränderst.


----------



## Gast2 (10. Jan 2013)

Ja richtig, SharePreferences statt Preferences.

Habe viel probiert und getestet und bin zu keinen brauchbaren Ergebnis gekommen.
Im Moment denke ich, dass 
	
	
	
	





```
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
```
weiterhelfen könnte. Nur tuts das nich. Ob es am Parameter liegt?

registerOnSharedPreferenceChangeListener() ist das Vernünftigste, was sich auf sharedPreferneces aufrufen läßt.

siehe auch SharedPreferences | Android Developers oder SharedPreferences.OnSharedPreferenceChangeListener | Android Developers

???:L

PS: aktuelle Version auf http://www.mehlhop.com/data/PraeferenzenTest.zip


----------

