2011-07-17 12 views
9

Le mie preferenze attivano l'evento onSharedPreferenceChanged dopo una modifica. Funziona con tutte le preferenze: casella di controllo, elenco, personalizzato, ecc. Ma non verrà chiamato se seleziono una suoneria da RingtonePreference. Ho questo codice:RingtonePreference non attivato 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" /> 

E la mia classe:

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); 
    } 
} 
} 

tutte le preferenze, ad eccezione del RingtonePreference, raggiunge il metodo onSharedPreferenceChanged. Qualcuno ha un'idea? Grazie.

risposta

13

Ho lottato con lo stesso problema che sembra essere un bug nel sistema Android. Dopo aver eseguito il debug del codice, ho notato che il listener non viene aggiunto alla nostra mappa degli ascoltatori RingtonePreference, a differenza di altre classi come ListPreference.

I opened a ticket, ma per ora ho trovato un modo per superarlo utilizzando OnPreferenceChangeListener. Il mio codice imposta il riepilogo delle preferenze sulla suoneria selezionata, è possibile utilizzare la logica.

primo a rendere la vostra attività di implementare OnPreferenceChangeListener e scrivere il metodo 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"); 
} 

Si noti che a differenza onSharedPreferenceChanged, onPreferenceChange si chiama prima la preferenza viene aggiornato, quindi è necessario utilizzare il parametro newValue per ottenere i dati selezionati invece di ottenerlo dalla preferenza.

Quindi, impostare l'ascoltatore in 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); 

} 

Spero che questo aiuti.

+1

Grazie per aver ricordato questo bug, che mi stava facendo impazzire. Ho notato, tuttavia, che se nel tuo 'onResume()' stai già impostando i valori di 'summary' iniziali (dal momento che probabilmente vorrai vedere le impostazioni correnti al primo accesso a' PreferenceActivity'), poi quando andrai per scegliere una nuova suoneria dalla finestra di dialogo che si apre, dopo che la finestra di dialogo si chiude il 'PreferenceActivity''s 'onResume' verrà richiamato comunque e il riepilogo della preferenza della suoneria verrà aggiornato. Quindi potrebbe non essere necessario usare questa soluzione alternativa se stavi già impostando i valori iniziali in 'onResume' –

9

Ho anche pensato che si trattasse di un bug nel sistema all'inizio, ma il problema è in realtà più sottile. RingtonePreference lancia una nuova attività tramite un intento. Ciò significa che PreferenceActivity viene messo in pausa. E stai annullando la registrazione dell'ascoltatore in onPause(). Se non lo fai, funzionerà bene (almeno lo ha fatto per me).

Ma naturalmente, non è possibile far registrare il gestore per sempre. Ho compromesso usando onStart()/onStop() invece di onResume()/onPause().

+0

Grazie per questa risposta. Stavo seguendo le best practice di Android, che come hai sottolineato, è utilizzare onResume()/onPause() per registrare/annullare la registrazione del listener. Ho modificato la registrazione/annullamento della registrazione su onStart()/onStop() come suggerito e ora funziona perfettamente! –

+0

Poiché 'RingtonePreference' lancia un intent, l'altro problema potrebbe essere l'override' onActivityResult'.Avevo un'altra attività che stavo lanciando dal mio 'PreferenceActivity' e nel mio' onActivityResult' non ho mai chiamato il metodo super. – ashishduh

0

ho dovuto impostare manualmente l'OnPreferenceChangeListener me sul mio 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; 
     } 
    }); 
Problemi correlati