2011-07-17 12 views
9

Moje preferencje wszystkie powodują zdarzenie onSharedPreferenceChanged po zmianie. Działa dla wszystkich preferencji: Pole wyboru, Lista, niestandardowe itp. Ale nie zostanie wywołane, jeśli wybiorę dzwonek z opcji DzwonekPreferencyjny. Mam ten kod:RingtonePreference nie wyzwala onSharedPreferenceChanged

<CheckBoxPreference android:title="@string/pref_notification" 
     android:defaultValue="true" android:summary="@string/pref_notification_summary" 
     android:key="prefNotification" /> 
    <RingtonePreference android:title="@string/pref_ringtone" 
      android:key="prefRingtone" 
      android:summary="@string/pref_ringtone_summary" android:ringtoneType="all" /> 
    <CheckBoxPreference android:title="@string/pref_vibrate" 
     android:defaultValue="true" android:summary="@string/pref_vibrate_summary" 
     android:key="prefVibrationOn" /> 
    <ListPreference android:title="@string/pref_notification_interval" 
     android:summary="@string/pref_notification_interval_summary" 
     android:key="prefNotificationInterval" android:defaultValue="60" 
     android:entries="@array/prefs_interval" android:entryValues="@array/prefs_interval_values" /> 

i moja klasa:

public class TimePrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    context = this; 

    addPreferencesFromResource(R.layout.preferences);   

    Preference dbPref = (Preference) findPreference("prefDeleteDb");  
    dbPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { 

     public boolean onPreferenceClick(Preference preference) 
     { 
      showWipeDbDialog(); 
      return true; 
     } 
    }); 
} 

@Override 
public void onResume() { 
    super.onResume(); 

    prefs = PreferenceManager.getDefaultSharedPreferences(this); 
    prefs.registerOnSharedPreferenceChangeListener(this); 

    toggleEnableList(); 
} 

@Override 
public void onPause() { 
    prefs.unregisterOnSharedPreferenceChangeListener(this); 

    super.onPause(); 
} 

@Override 
public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) 
{ 
    boolean enabled = toggleEnableList();   

    if (enabled) 
    { 
     OnBootReceiver.setAlarm(TimePrefsActivity.this);     
    } 
    else 
    { 
     OnBootReceiver.cancelAlarm(TimePrefsActivity.this); 
    } 
} 
} 

wszystkie preferencje, z wyjątkiem RingtonePreference, dotrzeć metodę onSharedPreferenceChanged. Czy ktoś ma pomysł? Dzięki.

Odpowiedz

13

Zmagałem się z tym samym problemem, który wydaje się być błędem w systemie Android. Po debugowaniu kodu zauważyłem, że słuchacz nie jest dodany do naszej listy słuchaczy RingtonePreference, w przeciwieństwie do innych klas, takich jak ListPreference.

I opened a ticket, ale na razie znalazłem sposób na pokonanie go za pomocą OnPreferenceChangeListener. Mój kod ustawia podsumowanie preferencji wybranego dzwonka, zamiast tego możesz użyć swojej logiki.

Pierwszy dokonać aktywność realizować OnPreferenceChangeListener i napisać metodę onPreferenceChange

@Override 
public boolean onPreferenceChange(Preference preference, Object newValue) { 
    updateRingtoneSummary((RingtonePreference) preference, Uri.parse((String) newValue)); 
    return true; 
} 

private void updateRingtoneSummary(RingtonePreference preference, Uri ringtoneUri) { 
    Ringtone ringtone = RingtoneManager.getRingtone(this, ringtoneUri); 
    if (ringtone != null) 
     preference.setSummary(ringtone.getTitle(this)); 
    else 
     preference.setSummary("Silent"); 
} 

Zauważ, że w przeciwieństwie do onSharedPreferenceChanged, onPreferenceChange nazywa przed preferencja jest aktualizowany, więc należy użyć parametru nowaWartość dostać wybrane dane zamiast odbierać je z preferencji.

Następnie ustaw słuchacza na OnResume:

@Override 
protected void onResume() { 
    super.onResume(); 

    // A patch to overcome OnSharedPreferenceChange not being called by RingtonePreference bug 
    RingtonePreference pref = (RingtonePreference) findPreference(getString(R.string.pref_ringtone)); 
    pref.setOnPreferenceChangeListener(this); 

} 

nadzieję, że to pomaga.

+1

Dzięki za wskazanie tego błędu, to było doprowadza mnie do szału. Zauważyłem jednak, że jeśli w swoim 'onResume()' już ustawiasz początkowe wartości 'summary' (ponieważ prawdopodobnie będziesz chciał zobaczyć bieżące ustawienia po pierwszym wprowadzeniu' PreferenceActivity'), to kiedy pójdziesz aby wybrać nowy dzwonek z wyskakującego okna dialogowego, po zamknięciu okna dialogowego 'onResume' 'PreferenceActivity' zostanie ponownie wywołany, a podsumowanie preferencji Dzwonek zostanie zaktualizowane. Tak więc może nie być konieczne użycie tego obejścia, jeśli już ustawiłeś wartości początkowe w 'onResume' –

9

Też myślałem, że to był błąd w systemie na początku, ale problem jest w rzeczywistości bardziej subtelny. RingtonePreference uruchamia nową aktywność za pomocą intencji. Oznacza to, że twoja PreferenceActivity zostaje wstrzymana. I wyrejestrujesz swojego słuchacza w funkcji onPause(). Jeśli tego nie zrobisz, wszystko będzie dobrze (przynajmniej dla mnie).

Ale naturalnie nie możesz pozwolić swojemu handlerowi na pozostanie zarejestrowanym na zawsze. Zaatakowałem przy użyciu metody onStart()/onStop() zamiast onResume()/onPause().

+0

Dziękuję za tę odpowiedź. Śledziłem najlepsze praktyki Androida, które, jak zauważyłeś, polegają na użyciu onResume()/onPause() w celu zarejestrowania/wyrejestrowania odbiorcy. Zmieniłem jego rejestrację/wyrejestrowanie na onStart()/onStop(), jak sugerowałeś i teraz działa pięknie! –

+0

Ponieważ 'RingtonePreference' uruchamia intencję, innym problemem może być nadpisanie' onActivityResult'.Miałem inne działanie, które uruchamiałem z mojego "PreferenceActivity" i mojego "onActivityResult", do którego nigdy nie odwołałem się do metody super. – ashishduh

0

musiałem ręcznie ustawić OnPreferenceChangeListener ja na moim SettingsFragment:

Preference notificationSoundPref = findPreference(Constants.PREFS_NOTIFICATION_SOUND); 
    notificationSoundPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 
     @Override 
     public boolean onPreferenceChange(Preference preference, Object newValue) { 
      // do what you need here 
      return true; 
     } 
    }); 
Powiązane problemy