I am a beginner in android and I have a confusion regarding Shared Preferences implementation. My goal is to use a string where a user defines some text which will be used in MainFragment. Given the fact that user may change that string when application is running I need a listener as well. So according to one book so far I have a SettingsActivity and a SettingsFragment.
SettingsActivity so far:
public class SettingsActivity extends AppCompatActivity {
private SharedPreferences prefs;
private String stringIWantToSave;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
getFragmentManager().beginTransaction().
replace(android.R.id.content, new SettingsFragment(), "settings_fragment").commit();
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
}
#Override
protected void onResume() {
super.onResume();
stringIWantToSave = prefs.getString("stringIWantToSave", "myString");
}
}
SettingsFragment so far:
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
private SharedPreferences sharedPreferences;
private String stringIWantToSave;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
}
#Override
public void onPause() {
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
super.onPause();
}
#Override
public void onResume() {
super.onResume();
sharedPreferences.getString("stringIWantToSave", "myString");
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
}
My questions are:
• In which method and how should I save the changed value from the user?
• How can I implement the listener so that it will inform the MainFragment that the string has changed?
1. To achieve the SettingsActivity with EditTextPreference, first you have to create a PreferenceScreen that contains EditTextPreference.
preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<EditTextPreference
android:key="pref_key_name"
android:title="Name"
android:summary="Enter your name here!"
android:dialogTitle="Enter name:">
</EditTextPreference>
</PreferenceScreen>
2. Create a Fragment extending PreferenceFragment. Do preference initialization and add OnSharedPreferenceChangeListener to update the UI when user input their name.
SettingsFragment.java:
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
// Preference Keys
public static final String KEY_PREF_NAME = "pref_key_name";
// Shared preference
SharedPreferences mSharedPreferences;
// Name preference
EditTextPreference mPreferenceName;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
// Shared preference
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
// Name preference
mPreferenceName = (EditTextPreference) getPreferenceScreen().findPreference(KEY_PREF_NAME);
// Initialize
initPreferences();
}
public void initPreferences()
{
// Name
String oldName = mSharedPreferences.getString(KEY_PREF_NAME, "Enter your name here!");
// Update view
mPreferenceName.setSummary(oldName);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPref, String key) {
if(key.equals(KEY_PREF_NAME))
{
// Name
String currentName = sharedPref.getString(key, "DEFAULT_VALUE");
// Update view
mPreferenceName.setSummary(currentName);
}
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
}
3. Finally, Create SettingsActivity and show SettingsFragment on its FrameLayout.
SettingsActivity.java:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
// Settings Fragment
SettingsFragment settingsFragment = new SettingsFragment();
getFragmentManager().beginTransaction().replace(R.id.content, settingsFragment).commit();
}
#Override
protected void onResume() {
super.onResume();
}
}
HOW TO USE:
To use updated name from preference, get the name value from preference inside your activity or fragments onResume() method:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
// Name
String name = sharedPreferences.getString(SettingsFragment.KEY_PREF_NAME, "DEFAULT_VALUE");
// Do something with name
................
........................
}
}
OUTPUT:
Hope this will help~
Related
I am trying to listen SharedPreferences changes in the MainActivity. And update the values in the settings of the app. And the working code goes like:
private SharedPreferences SP, prefs;
SharedPreferences.OnSharedPreferenceChangeListener mListener;
SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
mListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
Toast.makeText(MainActivity.this, "Key changed: "+key, Toast.LENGTH_SHORT).show();
}
};
SP.registerOnSharedPreferenceChangeListener(mListener);
But when I try to change the key value like this. It says can not resolve findPreference method. I tried doing it using context but still the error persists.
private SharedPreferences SP, prefs;
SharedPreferences.OnSharedPreferenceChangeListener mListener;
SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
mListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("username")) {
Preference pref = findPreference(key);
pref.setDefaultValue(prefs.getString(key, "bob")); }
};
SP.registerOnSharedPreferenceChangeListener(mListener);
How can we import the method definition in MainActivity. Please tell if the way I am changing value here, if correct?
Settings.java
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.os.Bundle;
public class Settings extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
}
public static class MyPreferenceFragment extends PreferenceFragment
{
PrefManager prefManager;
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
}
preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference android:title="Your Name"
android:key="username"
android:summary="Please provide your username">
</EditTextPreference>
</PreferenceScreen>
I basically want to update the Preference in the settings page whenever SharedPreferences of key "username" is getting changed in the code.
You must implement PreferenceActivity in your activity
Add extends PreferenceActivity after your activity name and then import it's namespace:
public class MainActivity extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}
}
For more info look at http://developer.android.com/reference/android/preference/PreferenceActivity.html
EDITED
Use the following code:
public class Settings extends PreferenceActivity {
private SharedPreferences SP;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
SharedPreferences.OnSharedPreferenceChangeListener mListener;
SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
}
public static class MyPreferenceFragment extends PreferenceFragment implements
SharedPreferences.OnSharedPreferenceChangeListener{
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("username")) {
Preference pref = findPreference(key);
pref.setDefaultValue(prefs.getString(key, "bob"));
}
}
}
}
i have setup an onpreference click listener for a preference but it fails to fire even though the preference is found by the find preference command.
Activity
public class PreferenceActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content
setContentView(R.layout.activity_preference);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
}
}
public static class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
Context context;
private final String DOB = "date";
private SharedPreferences prefs;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
context = getActivity().getApplicationContext();
Preference dob = findPreference(DOB);
Log.i("test", dob.getKey() + "");
dob.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
Log.i("test", "2");
return false;
}
});
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
}
}
The preference xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="My Account">
<EditTextPreference
android:key="profile_name"
android:summary="Taylor Swift"
android:title="Username" />
<Preference
android:key="date"
android:summary="N.A."
android:title="#string/date" />
</PreferenceCategory>
</PreferenceScreen>
The log output for "test" correctly displays the key of the preference but the log within the onclick never fires.
I've created simple project with your code and everything seems to be working fine.
Log.i("test", "2");
is being called when I click "Date" field.
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
getFragmentManager().beginTransaction()
.add(R.id.settingsContainer, new SettingsFragment())
.commit();
}
public static class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("aKey") {
Preference pref = findPreference(key);
pref.setSummary(sharedPreferences.getString(key, ""));
}
}
}
}
When the user changes his preferences they are stored and showed by the listener.
When the activity is restarted I lost all the summaries, but values are correctly stored because they are retrieved if I click on each preference.
I'd like to show what was done before, not default values.
In your onResume() method after registering the listener just call the listener with every preference key.
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(getPreferenceScreen().getSharedPreferences(), "your_key");
}
when the Fragment was created, you call the following method:
addPreferencesFromResource(R.xml.preferences)
the if the xml file preferences content is stationary, and you change another preference file when accept onSharedPreferenceChanged.
May you can get values with method getActivity().getSharedPreferences().
I've my main activity that starts a new activity (SearchResultsActivity).
I also have a settings menu.
I want my SearchResultsActivity to be notified every time there is a new/edited setting from the settings menu.
I'm implementing the OnSharedPreferenceChangeListener the interface on SearchResultsActivity and registering itself to listen to any modification in the settings but for some odd reason the callback is never executed.
Here's my SearchResultsActivity code
public class SearchResultsActivity extends BaseActivity implements SearchResultsFragment.RouteResultsFragmentCommunicator, SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = SearchResultsActivity.class.getSimpleName();
private FragmentManager mFragmentManager;
private SearchResultsFragment mSearchResultsFragment;
private RouteFragment mRouteFragment;
private SharedPreferences pref;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_results);
// Set the toolbar
activateToolbarWithHomeEnabled();
pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
// Initialize the FragmentManager
mFragmentManager = getFragmentManager();
mSearchResultsFragment = (SearchResultsFragment) mFragmentManager.findFragmentById(R.id.searchRouteResultsFragment);
}
#Override
protected void onResume() {
super.onResume();
pref.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
protected void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
#Override
protected void onPause() {
pref.unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "onSharedPreferenceChanged callback");
}
}
For sake of simplicity I've removed parts of the code that has nothing to do with my issue.
So my problem is, "onSharedPreferenceChanged callback" is never printed on the logcat when I make a change on any setting.
Just in case, here's my settings implementation:
public class MySettings extends BaseActivity {
private static final String TAG = MySettings.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pref_with_actionbar);
// Set the toolbar
activateToolbarWithHomeEnabled();
getFragmentManager().beginTransaction().replace(R.id.content_frame, new MyPreferenceFragment()).commit();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id==android.R.id.home) {
finish();
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
}
And the fragment:
public class MyPreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = MyPreferenceFragment.class.getSimpleName();
private EditTextPreference mMaxRadius;
private SharedPreferences mSharedPreferences;
private CheckBoxPreference mCheckBoxPreference;
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
mMaxRadius = (EditTextPreference) findPreference(getResources().getString(R.string.pref_radius_key));
mSharedPreferences = getPreferenceManager().getSharedPreferences();
String maxRadius = mSharedPreferences.getString(getResources().getString(R.string.pref_radius_key), "Unknown");
mMaxRadius.setSummary("Max Radius: " + maxRadius);
mCheckBoxPreference = (CheckBoxPreference) findPreference(getString(R.string.pref_order_list_key));
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equalsIgnoreCase(getResources().getString(R.string.pref_radius_key))) {
Preference connectionPref = findPreference(key);
// Set summary to be the user-description for the selected value
connectionPref.setSummary(sharedPreferences.getString(key, "Unknown") + " km");
}
else if (key.equalsIgnoreCase(getString(R.string.pref_order_list_key))) {
Preference orderByPreference = findPreference(key);
}
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
}
Please note that on MyPreferenceFragment the onSharedPreferenceChanged is called as expected, eveytime there is a settings change the MyPreferenceFragment#onSharedPreferenceChanged is executed. But SearchResultsActivity#onSharedPreferenceChanged is never called.
Can someone explain me what is wrong with SearchResultsActivity#onSharedPreferenceChanged never being executed when I change something on the settings?
Register your listener in onCreate() and unregister in onDestroy(). When you start the preference activity your main activity is paused, and unregisters.
I've got a problem with updating the summary value of a PreferncesFragment. I have tried to follow the advice of the post : Updating sharedPreferences Summary via listener but it doesn't work ! The summary doesn't update...
I don't understand what is wrong ? Thank's for your help !
My pref file :
<CheckBoxPreference
android:key="is_title"
android:summary="#string/conf_istitle_sum"
android:title="#string/conf_istitle_title"
android:defaultValue="true"
/>
<EditTextPreference
android:key="sms_title"
android:title="#string/conf_sms_title"
android:summary="#string/msgtitre"
android:dialogTitle="#string/conf_diagsms_title"
android:dialogMessage="#string/conf_diagsms_sum"
android:defaultValue="#string/msgtitre"
/>
My Preference class :
public class SetPreferenceActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener
{
protected MyPreferenceFragment settingsFragment;
#Override
protected void onCreate(final Bundle savedInstanceState)
{ settingsFragment = new MyPreferenceFragment();
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content,
settingsFragment).commit();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals("sms_title")) {
String newValue = sharedPreferences.getString(key, "");
settingsFragment.findPreference(key).setSummary(newValue);
}
}
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
}
What's working is the "old" solution deprecated OldPreferences
Please check whether onSharedPreferenceChanged is being called at all. You need to register the handler with your preferences. First,
get a reference to your preferences in onCreate:
public class SettingsActivity
extends AppCompatActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
// ...
}
In the lifecycle of the Activity (note that I am using a plain AppCompatActivityrather than a PreferenceActiviy) register the handeler.
#Override
protected void onPause() {
super.onPause();
preferences.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
protected void onResume() {
super.onResume();
preferences.registerOnSharedPreferenceChangeListener(this);
}
Now, the handler should be called:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(DEBUG_TAG, key);
// fragment.findPreference(key) //... TBD
}