Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RingtonePreference not firing onSharedPreferenceChanged

Tags:

android

My Preferences all trigger the onSharedPreferenceChanged event upon a change. It works for all preferences: Checkbox, List, custom, etc. But it won't be called if I select a ringtone from the RingtonePreference. I have this code:

    <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" />

And my class:

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

All the preferences, except the RingtonePreference, reach method onSharedPreferenceChanged. Does anyone have an idea? Thanks.

like image 510
widi Avatar asked Jul 17 '11 16:07

widi


2 Answers

I struggled with the same problem which seems to be a bug in the android system. After debugging the code I noticed the listener is not added to our RingtonePreference listeners map, unlike other classes like ListPreference.

I opened a ticket, but for now I found a way to overcome it using OnPreferenceChangeListener. My code sets the preference summary to the selected ringtone, you can use your logic instead.

First make your activity implement OnPreferenceChangeListener and write the onPreferenceChange method

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

Notice that unlike onSharedPreferenceChanged, onPreferenceChange is called before the preference is updated, so you must use the newValue parameter to get the selected data instead of getting it from the preference.

Then, set the listener on 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);

}

Hope this helps.

like image 112
Arad Avatar answered Oct 20 '22 20:10

Arad


I also thought this was a bug in the system at first, but the issue is actually more subtle. RingtonePreference launches a new activity via an intent. This means that your PreferenceActivity gets paused. And you're unregistering your listener in onPause(). If you don't do this, it'll work fine (at least it did for me).

But naturally, you can't have your handler stay registered forever. I compromised by using onStart()/onStop() instead of onResume()/onPause().

like image 32
dlf Avatar answered Oct 20 '22 19:10

dlf