NullPointerException at getDefaultSharedPreferences - java

I'm creating a PreferenceFragment based on the developer guide but I get a NullPointerException at the getDefaultSharedPreferences() call in onCreate() when I try to restore saved user preferences. I inflate the PreferenceFragment from xml and I set default values too. The exception is thrown at getDefaultSharedPreferencesName() within getDefaultSharedPreferences().
Here is the PreferenceFragment class:
public class SettingsFragment extends PreferenceFragment implements
OnSharedPreferenceChangeListener {
public static final String KEY_MAX_WALK_DISTANCE_PREFERENCE = "max_walk_distance_preference";
public static final String KEY_MAX_SEARCH_TIME_PREFERENCE = "max_search_time_preference";
Context context = getActivity();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
// load user preferences
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
if (sharedPreferences != null) {
Preference walkDistance = findPreference(KEY_MAX_WALK_DISTANCE_PREFERENCE);
if (walkDistance != null) {
walkDistance.setSummary(sharedPreferences.getString(
KEY_MAX_WALK_DISTANCE_PREFERENCE, "")
+ getResources().getString(
R.string.max_walk_distance_postfix));
}
Preference searchTime = findPreference(KEY_MAX_SEARCH_TIME_PREFERENCE);
if (searchTime != null) {
searchTime.setSummary(sharedPreferences.getString(
KEY_MAX_SEARCH_TIME_PREFERENCE, "")
+ getResources().getString(
R.string.max_search_time_postfix));
}
}
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(KEY_MAX_WALK_DISTANCE_PREFERENCE)) {
Preference walkDistance = findPreference(key);
// Set summary to be the user-description for the selected value
walkDistance.setSummary(sharedPreferences.getString(key, "")
+ getResources().getString(
R.string.max_walk_distance_postfix));
} else if (key.equals(KEY_MAX_SEARCH_TIME_PREFERENCE)) {
Preference searchTime = findPreference(key);
// Set summary to be the user-description for the selected value
searchTime.setSummary(sharedPreferences.getString(key, "")
+ getResources()
.getString(R.string.max_search_time_postfix));
}
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
}
Here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<EditTextPreference
android:dialogTitle="#string/max_walk_distance_dialogtitle"
android:key="max_walk_distance_preference"
android:summary="#string/max_walk_distance_summary"
android:title="#string/max_walk_distance_title"
android:inputType="number"
android:defaultValue="500" />
<EditTextPreference
android:dialogTitle="#string/max_search_time_dialogtitle"
android:key="max_search_time_preference"
android:summary="#string/max_search_time_summary"
android:title="#string/max_search_time_title"
android:inputType="number"
android:defaultValue="10"/>
</PreferenceScreen>

Context context = getActivity();
Your fragment is not associated with any activity when the object is instantiated and getActivity() returns null. Hence the NPE when trying to get preferences with a null Context.
Postpone the getActivity() to e.g. your onCreate() (which is called after onAttach()).

getActivity returns untill onAttach is called. Change
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context)
with
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(getActivity())

Related

Problem with saving checkedtextview state, it misbehaves with multiple items

I made an activity consisting of CheckTextView's and TextView's. When the user checks the box, I want to save that state when the user leaves the activity or closes the app.
I added onClickListener to every CTV.
Then I try to save it in onPause and onResume methods. I can't troubleshoot this problem as the checkboxes work when I save just a few of them it works (it varies but it works with 1-5 of them) but when I add all of them they are not saved when I go back to the activity.
//this will always work and will save the state of the boxes
protected void onPause() {
super.onPause();
save(ctv1.isChecked());
save(ctv2.isChecked());
save(ctv3.isChecked());
}
protected void onResume() {
super.onResume();
ctv1.setChecked(load());
ctv2.setChecked(load());
ctv3.setChecked(load());
}
//when I add all of them, they are always either checked or unchecked
//it doesn't matter what combination of them I try, it seems that it is //always working with a couple of CTV's but fails with more than 5-6 of them
//this is how my onClickListener looks like
CheckedTextView ctv1 = (CheckedTextView) findViewById(R.id.ctvFOX1);
ctv1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ctv1.isChecked()) {
ctv1.setChecked(false);
}
else {
ctv1.setChecked(true);
}
}
});
//save and load methods
private void save(final boolean isChecked) {
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("check", isChecked);
editor.apply();
}
private boolean load() {
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
return sharedPreferences.getBoolean("check", false);
}
Because you only use one key to save the CheckedTextView's value!
private void save(final boolean isChecked, String key) {
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(key, isChecked);
editor.apply();
}
private boolean load(String key) {
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
return sharedPreferences.getBoolean(key, false);
}
protected void onPause() {
super.onPause();
save(ctv1.isChecked(), "check1");
save(ctv2.isChecked(), "check2");
save(ctv3.isChecked(), "check3");
}
protected void onResume() {
super.onResume();
ctv1.setChecked(load("check1"));
ctv2.setChecked(load("check2"));
ctv3.setChecked(load("check3"));
}

onSharedPreferenceChanged isn't called everytime a preference has been changed

I have a problem with onSharedPreferenceChanged is only called the first time when a MultiSelectListPreference has changed. I open my settings activity and change the value which works fine and onSharedPreferenceChanged is getting called. If I open the dialog again, it shows the correct entries selected. I select another entry and hit OK. onSharedPreferenceChanged should now getting called but isn't. If I now open the dialog again, no entries are selected. Am I missing something or did I do somethign wrong?
Here's my preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<MultiSelectListPreference
android:key="operations"
android:title="#string/pref_operations"
android:dialogTitle="#string/pref_operations"
android:entries="#array/pref_operations_entries"
android:entryValues="#array/pref_operations_values"
android:defaultValue="#array/pref_operations_default" />
</PreferenceScreen>
And my settings fragment
public class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener
{
public static final String KEY_OPERATIONS_PREFERENCE = "operations";
private MultiSelectListPreference operationsPreference;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
operationsPreference = (MultiSelectListPreference) getPreferenceScreen().findPreference(KEY_OPERATIONS_PREFERENCE);
}
#Override
public void onResume()
{
super.onResume();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
Set<String> operations = operationsPreference.getValues();
String summary = "";
for (String s : operations)
summary += s + " ";
operationsPreference.setSummary(summary);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause()
{
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
if (key.equals(KEY_OPERATIONS_PREFERENCE))
{
Set<String> operations = operationsPreference.getValues();
String summary = "";
for (String s : operations)
summary += s + " ";
operationsPreference.setSummary(summary);
}
}
}
Umm frankly I built my sharedPreferances differently...ill attach my code example and hopefully it'll be of use to you
here goes:
this is the sharedpreferences class
public class AppPreferences {
public static final String KEY_LANG = "language";
final String APP_SHARED_PREFS = AppPreferences.class.getSimpleName(); // Name
// of
// the
// file
// -.xml
private SharedPreferences _sharedPrefs;
private Editor _prefsEditor;
public AppPreferences(Context context) {
this._sharedPrefs = context.getSharedPreferences(APP_SHARED_PREFS,
Activity.MODE_PRIVATE);
this._prefsEditor = _sharedPrefs.edit();
}
public String getlanguage() {
return _sharedPrefs.getString(KEY_LANG, "");
}
public void savelanguage(String text) {
_prefsEditor.putString(KEY_LANG, text);
_prefsEditor.commit();
}
}
to use it youll need to create
in your class
private AppPreferences _appPrefs;
and an example for use is
_appPrefs = new AppPreferences(getApplicationContext());
_appPrefs.savelanguage("English");
language = _appPrefs.getlanguage();
this is how i built it... works like a charm... and not complicated at all
It's because you unregister the listener in your onPause callback method which is invoked when Dialog is shown in an Activity.

Android SharedPreferences is reset to default values. After restarting app

Sometimes after restarting the app resets the sharedpreferences on devices with API level > 13.
The sharedpreferences are set at the beginning of the app (first activity of the app).
code:
Public void saveCountry(Context context, String countryCode) {
SharedPreferences settingsActivity = context.getSharedPreferences("preferences", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settingsActivity.edit();
editor.putString("key_country", countryCode);
editor.commit();
setDefaultChannels(context);
}
public String getCountry(Context mContext) {
SharedPreferences settingsActivity = mContext.getSharedPreferences("preferences", Context.MODE_PRIVATE);
String country = settingsActivity.getString("key_country", null);
return country;
}
I dont know what im doing wrong and why it is happening. I noticed this specially after receiving a push-notification to a detailactivity.
Are you calling the saving methods at the beginning of your app like this?
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
saveCountry();
Because if you are, you are calling it every time at startup, so the country will be overridden with whatever data countryCode equals at startup, which could be nothing. So maybe you should have some code that only calls that on first run.
Here is how I have it implemented in my app.
boolean firstRun;
final SharedPreferences firstRunPref = getSharedPreferences(PREFS_NAME, 0);
firstRun = firstRunPref.getBoolean("firstRun", true);
if(firstRun==true){
saveCountry();
SharedPreferences.Editor editor3 = firstRunPref.edit();
editor3.putBoolean("firstRun", false);
editor3.commit();
}

CheckBoxPreference not ticking when selected in PreferencesActivity

When I click the "Settings" page, my CheckBoxPreference shows exactly how I want it to at this stage, however when I select it, the state does not change (i.e. from Unchecked to Checked).
It seems to be retaining the value of false (default) and still running onPreferenceChanged with false as the value passed. I am running code inside my onPreferenceChangedListener that is dependent on the value of the preference that is changed. As it stands I only have one preference in here.
activity_preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceScreen>
<CheckBoxPreference
android:summaryOn="true"
android:summaryOff="false"
android:key="isReg"
android:title="Receive Push Messages"
android:selectable="true"
android:enabled="true"
android:persistent="true" />
</PreferenceScreen>
</PreferenceScreen>
PrefsActivity.java:
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import com.google.android.gcm.GCMRegistrar;
public class PrefsActivity extends PreferenceActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.activity_preferences);
Preference isReg = (Preference) findPreference("isReg");
isReg.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
public boolean onPreferenceChange(Preference pref, Object arg1) {
boolean isReg = getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("isReg", false);
if (isReg){
ServerUtilities.register(getApplicationContext(), GCMRegistrar.getRegistrationId(getApplicationContext()));
}
else {
ServerUtilities.unregister(getApplicationContext(), GCMRegistrar.getRegistrationId(getApplicationContext()));
}
return isReg;
}
});
}
}
You are using the wrong preference widget as per in the code sample,
Preference isReg = (Preference) findPreference("isReg");
It should have been CheckBoxPreference as in
CheckBoxPreference isReg = (CheckBoxPreference) findPreference("isReg");
Edit
One thing I noticed, you're not handling the preference activity properly...consider this code, always, call the preference's commit method in order to save it!
public class PrefsActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener{
CheckBoxPreference isReg;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.activity_preferences);
PreferenceManager.setDefaultValues(this,R.xml.activity_preferences, false);
isReg = (CheckBoxPreference)findPreference("isReg");
if (isReg != null){
isReg.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
#Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
boolean blnIsReg = Boolean.getBoolean(newValue.toString());
Editor e = _prefs.edit();
e.putBoolean("isReg", blnIsReg);
e.commit();
return true;
}
});
}
}
}
#Override
public void onStart(){
super.onStart();
_prefs = PreferenceManager.getDefaultSharedPreferences(this);
}
The listener that is implemented must be in this fashion, which is how the changes are effective:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "onSharedPreferenceChanged; key = " + key);
}
By incorporating the listener, the logcat will show that the preference's key is indeed being changed, i.e. "isReg".
Update the values from the shared preferences in onResume()
method
SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(PrefsActivity.this);
boolean isReg = prefs.getBoolean("isReg", false);
Hope Try This it will help You

Shared preferences don't take effect until Preferences clicked

I'm writing an app for the Sony Smartwatch, using their SDK. Here's part of the main activity:
class SmartTickerActivity extends ControlExtension {
private Handler mHandler;
SmartTickerActivity(final String hostAppPackageName, final Context context, Handler handler) {
super(context, hostAppPackageName);
if (handler == null) {
throw new IllegalArgumentException("handler == null");
}
}
#Override
public void onStart() {
//do some stuff
PreferenceManager.setDefaultValues(mContext, R.xml.preference, false);
}
The problem is that the saved preferences aren't being applied on the Smartwatch when the application launches. Nor are the default preference values from XML. However, if I click on any of the app's preferences on the phone, the saved preference values are immediately applied to the Smartwatch.
Note that the main class has no onCreate() method, and that's throwing me for a loop.
Here's part of the Preference activity:
public class MyPreferenceActivity extends PreferenceActivity {
private OnSharedPreferenceChangeListener mListener = new OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry().toString());
}
if (pref instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
pref.setSummary(editTextPref.getText().toString());
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preference);
setSummaries();
setTypeface(SmartTickerActivity.mainLayout);
if (previewLayout != null) setTypeface(previewLayout);
// Handle read me
Preference readMe = findPreference(getText(R.string.preference_key_read_me));
readMe.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference readMe) {
showDialog(DIALOG_READ_ME);
return true;
}
});
// Handle about
Preference about = findPreference(getText(R.string.preference_key_about));
about.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference about) {
showDialog(DIALOG_ABOUT);
return true;
}
});
// Handle preview
Preference preview = findPreference(getText(R.string.preference_key_preview_dialog));
preview.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preview) {
showDialog(DIALOG_PREVIEW);
return true;
}
});
}
I'm rather inexperienced at Android development, so the problem might very well have nothing to do whatsoever with the Sony SDK. Can anyone help?
You are correct, the preferences of the official sample extensions are not loaded until the PreferenceActivity is shown for the first time. If you use correct default values when accessing the preferences, this should not be a problem.
If you would like for the preferences to be loaded when the extension is initiated the first time, you could extend the android.app.Application class, and the onCreate method.
For example:
public class MySmartWatchApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
PreferenceManager.setDefaultValues(this, R.xml.app_preferences, false);
}
}

Categories