When I change value in Shared Preference app got crash - android

http://i.stack.imgur.com/vnfQt.png
As shown above From settings when I change the value of temprature units from metric to imperial and press back button my app got crash and showing below error
http://i.stack.imgur.com/dBeHk.png
SettingsActivity
package com.example.poo.sunshine;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
public class SettingsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(R.id.container, new MyPreferenceFragment())
.commit();
}
public static class MyPreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add 'general' preferences, defined in the XML file
addPreferencesFromResource(R.xml.pref_general);
// For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
// updated when the preference changes.
PreferenceManager.getDefaultSharedPreferences(getActivity()).registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference locationPref = findPreference(getString(R.string.pref_location_key));
Preference unitsPref = findPreference(getString(R.string.pref_units_key));
prefChanged(sharedPreferences, locationPref, key);
prefChanged(sharedPreferences, unitsPref, key);
}
private void prefChanged(SharedPreferences sharedPreferences, Preference pref, String key) {
if (sharedPreferences instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list (since they have separate labels/values).
ListPreference listPreference = (ListPreference) sharedPreferences;
int prefIndex = listPreference.findIndexOfValue(key);
if (prefIndex >= 0) {
pref.setSummary(listPreference.getEntries()[prefIndex]);
} else {
pref.setSummary(sharedPreferences.getString(key, ""));
}
}
}
}
}

The problem is cause from the view of your Fragment is not yet attached to your SettingActivity.
To avoid this error, you can check with isAdded() before access views in your Fragment.
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(isAdded()){
Preference locationPref = findPreference(getString(R.string.pref_location_key));
Preference unitsPref = findPreference(getString(R.string.pref_units_key));
prefChanged(sharedPreferences, locationPref, key);
prefChanged(sharedPreferences, unitsPref, key);
}
}
Another solution and I would like to suggest as well.
You should register the preference changed listener in onViewCreated() in your Fragment. So that mean your Fragment is fully attached.
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
PreferenceManager.getDefaultSharedPreferences(getActivity())
.registerOnSharedPreferenceChangeListener(this);
}
Hope this will work!

Related

Android Preferences - change font size by user

I am looking for a solution for my app to let the user select the font size via settings menu. Like I am able to do in other apps e.g. Jota+. Here are some screen shots for a better understanding (sorry - my Jota+ is a German version):
As of now I installed already a settingsActivity which is using a FragmentManager to call a PreferenceFragment using my pref_main.xml as resource.
Any idea how I can archive this?
My SettingsActivity:
package com.wbapps.wbshoppinglist;
/**
* Created by Andreas on 2/15/2018.
*/
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.view.MenuItem;
public class SettingsActivity extends AppCompatPreferenceActivity {
private static final String TAG = SettingsActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// load settings fragment
getFragmentManager().beginTransaction().replace(android.R.id.content, new MainPreferenceFragment()).commit();
}
public static class MainPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_main);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
private static void bindPreferenceSummaryToValue(Preference preference) {
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String stringValue = newValue.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
}
else if (preference instanceof EditTextPreference) {
if (preference.getKey().equals("key_gallery_name")) {
// update the changed gallery name to summary filed
preference.setSummary(stringValue);
}
} else {
preference.setSummary(stringValue);
}
return true;
}
};
}
My AppCompatPreferenceActivity:
package com.wbapps.wbshoppinglist;
/**
* Created by Andreas on 2/15/2018.
*/
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A {#link PreferenceActivity} which implements and proxies the necessary calls
* to be used with AppCompat.
*/
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate;
#Override
protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(#Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
#Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
#Override
public void setContentView(#LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
#Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
#Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
#Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
#Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
#Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
#Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}
My pref_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="#string/pref_header_font_setting">
<Preference
android:summary="#string/pref_font_setting"/>
</PreferenceCategory>
<PreferenceCategory android:title="#string/pref_header_about">
<Preference
android:selectable="false"
android:summary="#string/summary_about" />
<Preference
android:summary="#string/app_version"
android:title="#string/title_version" />
</PreferenceCategory>
</PreferenceScreen>
Here you can see the project structure:
Many thanks
Andreas

Listen preference change and transfer boolean in checkbox to MainActivity

I have 2 file:
control_preferences.xml:`
<PreferenceCategory
android:title="#string/control_category">
<CheckBoxPreference
android:title="Debug Information ON/OFF"
android:defaultValue="false"
android:summary="Show debug information when ON"
android:key="checkboxPref" />
</PreferenceCategory>
`
SettingsActivity.java:
package com.sample;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String KEY_PREF_DEBUG = "checkboxPref";
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(KEY_PREF_DEBUG)) {
Toast.makeText(getApplicationContext(), "CLICK",
Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
public static class ControlPrefsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// load the preferences from an XML resource
addPreferencesFromResource(R.xml.fragmented_control_preferences);
}
}}
I have 2 questions:
Why when selecting or deselecting Checkbox Toast doesn't display?
How to store in SharedPreferences boolean from this CheckBox and later read this boolean in MainActivity.
1) Why when selecting or deselecting Checkbox Toast doesn't display?
Add below lines in on resume of your activity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(prefs);
2)How to store in SharedPreferences boolean from this CheckBox and later read this boolean in MainActivity?
Use below code to get value
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.getBoolean("key_value_given_in_preference_xml_file")
Use this instead of implementing interface
checkboxPref = (CheckBoxPreference) getPreferenceScreen().findPreference(your_key);
checkboxPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{
#Override
public boolean onPreferenceChange(Preference preference, Object newValue)
{
YOUR CODE
return false;
}
});
#Jawegiel
I insert this to:
public static class ControlPrefsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// load the preferences from an XML resource
addPreferencesFromResource(R.xml.fragmented_control_preferences);
final CheckBoxPreference checkboxPref = (CheckBoxPreference) getPreferenceManager().findPreference("checkboxPref");
checkboxPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{
#Override
public boolean onPreferenceChange(Preference preference, Object newValue)
{
Toast.makeText(getActivity().getApplicationContext(), "CLICK",
Toast.LENGTH_SHORT).show();
return false;
}
});
}
}
and it works :)
Thank you both :)
#Jawegiel
what if I would use Toast like "Debug: " + "boolean from this actually changed checkbox" In MainActivity i read this boolean through code:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplication‌​Context());
boolean check = prefs.getBoolean("checkboxPref",false);
How read this boolean in in SettingsActivity same like in MainActivity?
I try through this code:
checkboxPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{
#Override
public boolean onPreferenceChange(Preference preference, Object newValue)
{
boolean check = checkboxPref.getSharedPreferences().getBoolean("checkboxPref",false);
Toast.makeText(getActivity().getApplicationContext(), "Debug " + check,
Toast.LENGTH_SHORT).show();
return false;
}
});
But now I can't unclick Checkbox or click if false :d

Update widget when preferences changed using custom broadcast

I need to update my app's widget every time the settings are changed by the user.
I have a settings activity:
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
public class SettingsActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String customIntent = "CUSTOM_SETTINGS_CHANGED";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new MainActivity.SettingsFragment())
.commit();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Intent intent = new Intent();
intent.setAction(customIntent);
this.sendBroadcast(intent);
}
}
I've added that custom intent to the manifest:
<action android:name="CUSTOM_SETTINGS_CHANGED" />
But the widget is not updated immediately after the settings are changed. So my custom broadcast either is not sent or not received. What's wrong with my code?
// this part important in manifest declaration
package com.xmpls.onetwothree.abc;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
public class SettingsActivity {
public class SettingsActivity extends Activity implements
SharedPreferences.OnSharedPreferenceChangeListener {
// Change like this
public static final String CUSTOM_SETTINGS_CHANGED = "com.xmpls.onetwothree.abc.custompls";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction();
/* More code here. . .*/
}
/* And some here. . .*/
}
================================================================================
and in manifest U must registred ACTION like this:
<action android:name="com.xmpls.onetwothree.abc.CUSTOM_SETTINGS_CHANGED" />
I've used a different approach.
In my main activity I've added this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
<...>
SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
Intent intent = new Intent();
intent.setAction(customIntent);
sendBroadcast(intent);
}
};
<...>
}
It seems that onSharedPreferenceChanged was never called for some reason. I don't know why but at least I've found a way to make this work.

Retrieving data from settings page in live wallpaper

Consider following code be the settings page of a live wallpaper in Android:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="#string/livewallpaper_settings"
android:key="livewallpaper_settings">
<ListPreference
android:key="livewallpaper_testpattern"
android:title="#string/livewallpaper_settings_title"
android:summary="#string/livewallpaper_settings_summary"
android:entries="#array/livewallpaper_testpattern_names"
android:entryValues="#array/livewallpaper_testpattern_prefix"/>
<CheckBoxPreference android:key="livewallpaper_movement"
android:summary="#string/livewallpaper_movement_summary"
android:title="#string/livewallpaper_movement_title"
android:summaryOn="Moving test pattern"
android:summaryOff="Still test pattern"/>
</PreferenceScreen>
It shows a setting page and everything about showing the settings is ok. How can I save this settings and use them while creating the live wallpaper?
Also, is it true to read the settings in onCreate method or not?
I found the answer :
package ca.jvsh.livewallpaper;
import ca.jvsh.livewallpaper.R;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class LiveWallpaperSettings extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener
{
#Override
protected void onCreate(Bundle icicle)
{
super.onCreate(icicle);
getPreferenceManager().setSharedPreferencesName(LiveWallpaper.SHARED_PREFS_NAME);
addPreferencesFromResource(R.xml.livewallpaper_settings);
getPreferenceManager().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onResume()
{
super.onResume();
}
#Override
protected void onDestroy()
{
getPreferenceManager().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key)
{
}
}
this was the java class for the setting page.
and this is for reading the settings :
TestPatternEngine()
{
...
mPreferences = LiveWallpaper.this.getSharedPreferences(SHARED_PREFS_NAME, 0);
mPreferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(mPreferences, null);
}
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key)
{
mShape = prefs.getString("livewallpaper_testpattern", "smpte");
mMotion = prefs.getBoolean("livewallpaper_movement", true);
readColors();
}

Android Using SharedPreferences to save and retrieve values - Counter

Hello I am new to android and actually i am developing a application whereby the user would be clicking on a button and the button should record the click event - the counter should be incremented at each time the button is clicked. The button would be displayed in one activity and once the user has clicked the button, another activity would be displayed whereby the results would be shown.
Actually i am having problems in assigning the sharedPreferences to the button and then displaying it into the next activity hence having the number of clicks.
The code i am using is as follows:
MainActivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
/** Declare the variables being used */
public static final String GAME_PREFERENCES = "GamePrefs";
public static final String GAME_PREFERENCES_SCORE = "Score"; // Integer
int counter;
Button add;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
counter = 0;
add = (Button) findViewById (R.id.bAdd);
add.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
counter++;
Intent openClickActivity2 = new Intent("com.android.jay.Results");
startActivity(openClickActivity2);
}
});
}
}
Results.java
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.TextView;
public class Results extends MainActivity{
public void onCreate(Bundle savedInstanceState) {
SharedPreferences mGameSettings;
super.onCreate(savedInstanceState);
mGameSettings = getSharedPreferences(GAME_PREFERENCES, Context.MODE_PRIVATE);
setContentView(R.layout.results);
final TextView DisplayResults =
(TextView) findViewById(R.id.bAdd);
if (mGameSettings.contains(GAME_PREFERENCES_SCORE)) {
DisplayResults.setText(mGameSettings.getString(GAME_PREFERENCES_SCORE, “counter”));
}
}
}
Any help to guide me would be much appreciated.Thank you
You will have to set GAME_PREFERENCES_SCORE in MainActivity. Do something like this after counter++:
getSharedPreferences(GAME_PREFERENCES, Context.MODE_PRIVATE).edit().setInt(GAME_PREFERENCES_SCORE, counter). commit();
Simply make a Preferences class
public class Preferences {
String MASTER_NAME = "mysticmatrix_master";
SharedPreferences mysticMatrixPref;
Preferences(Context context) {
mysticMatrixPref = context.getSharedPreferences(MASTER_NAME, 0);
}
public void setAddCount(int count) {
SharedPreferences.Editor prefEditor = mysticMatrixPref.edit();
prefEditor.putInt("count", count);
prefEditor.commit();
}
public int getAddCount() {
return mysticMatrixPref.getInt("count", 0);
}
}
and in your MainActivity.java put this code
public class MainActivity extends Activity implements OnClickListener {
ImageButton add;
Preferences cpObj;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preferences = new Preferences(getApplicationContext());
/*
* getting the count variable and adding 1 in that to check the condition of showing rate activity and adds
*/
add = (Button) findViewById (R.id.bAdd);
add.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cpObj = new Preferences(getApplicationContext());
cpObj.setAddCount(cpObj.getAddCount() + 1);
}
});
}
}
And in your result activity just get the count's value
import android.content.Context;
public class Results extends MainActivity{
Preferences cpObj;
public void onCreate(Bundle savedInstanceState) {
preferences = new Preferences(getApplicationContext());
setContentView(R.layout.results);
final TextView DisplayResults =
(TextView) findViewById(R.id.bAdd);
DisplayResults.setText(cpObj.getAddCount());
}
} }
By this you will get the default value of result as '0' and you can set that in your Preferences class
Use a method like this:
public static void SavePreference(Context context, String key, Integer value) {
SharedPreferences.Editor editor = PreferenceManager
.getSharedPreferences(GAME_PREFERENCES, Context.MODE_PRIVATE)
.edit();
editor.putInt(key, value);
editor.commit();
}
and in you onclick after counter++ add this:
SavePereference(context, "GAME_PREFERENCES_SCORE", counter);

Categories

Resources