I looked around but couldn't find a single tutorial that tells me how to use the switchpreference in my preference activity and in my main activity. I want to know how to implement it in my application using sharedpreference. Sample code would be appreciated. Thanks in advance
preference.xml:
<SwitchPreference
android:key="test"
android:title="Test" />
PreferenceActivity:
public class TestPrefActivity extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.sample);
}
}
Register the shared preference object for the changes
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(MainActivity.this);
sharedPrefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
boolean test = sharedPreferences.getBoolean("test", false);
Log.e(TAG, "Value:" + test);
}
});
I'm having a comparable issue with another establishment of mine. I fixed it by using <SwitchPreference android:key="test" android:title="Test" />
Related
I have an Activity containing a PreferenceFragment. The user can change the app's style (light theme or dark theme) in this Activity. Now I want the change being visible immediately. That means, I want the style of the Activity changing when the user changes the style setting in the PreferenceFragment.
My idea was to listen for the preference change with OnSharedPreferenceChangeListener in the PreferenceFragment and recreate the Activity.
But I do not think this is the right way. So, what is best practice here? Thanks in advance.
UPDATE
Activity:
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadSettings();
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
private void loadSettings() {
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(this);
boolean darkTheme =
sharedPreferences.getBoolean(getText(R.string.pref_theme_key).toString(), false);
if (darkTheme) {
setTheme(R.style.DarkTheme);
}
}
}
PreferenceFragment:
public class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(getText(R.string.pref_theme_key))) {
// recreate Activity
}
}
}
Preferences:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="false"
android:key="#string/pref_theme_key"
android:title="#string/pref_theme" />
</PreferenceScreen>
I think your approach is correct. Listen for that preference change and then recreate your activity.
Editing for more context:
You should be saving this as a light/dark variant in your preferences and then when your activity is created call setTheme based on this before calling setContentView.
Because I want an AppCompat Action Bar on all of my settings submenus, I had to implement a workaround and my Settings Activity extends AppCompatActivity, not PreferenceActivity. I'm using a PreferenceFragment in the activity to handle the preferences, and each PreferenceScreen has its own xml file, which the PreferenceFragment switches out for each submenu in the settings. All of this was necessary to get the Action Bar to stay put through all of my submenus.
I'm trying to read a string value from the shared preferences file from within my MainActivity, and I've tried three different methods for getting that information, none of which have worked:
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String btSelectPref = sharedPref.getString(getString(R.string.bt_select_key), "");
,
SharedPreferences sharedPref = getSharedPreferences(name, MODE_PRIVATE);
String btSelectPref = sharedPref.getString(getString(R.string.bt_select_key), "");
and
SharedPreferences sharedPref = getPreferences(MODE_PRIVATE);
String btSelectPref = sharedPref.getString(getString(R.string.bt_select_key), "");
Here is the relevant section of my preferences.xml:
<PreferenceCategory
android:title="Bluetooth"
android:key="pref_bt">
<Preference
android:title="Select Bluetooth Device"
android:key="#string/bt_select_key"
android:defaultValue="0">
</Preference>
</PreferenceCategory>
This should fill the btSelectPref string with a "0", but it's always empty when I test it. I have included PreferenceManager.setDefaultValues(this, R.xml.preferences, false); in onCreate in my MainActivity, so the default values should be set.
I'm not sure which of these methods I should be using since I have multiple resource files for my settings, but none of them seem to be working for me. In the case of getSharedPreferences(name, MODE_PRIVATE), I have no idea what the name parameter should be referencing, since I've never named my shared preferences file.
EDIT: It turns out my issue was not related to getting values from the shared preferences file. I just had the wrong xml tag on the preference I was trying to check the value of. I changed it from a generic <Preference> tag to a <ListPreference> and my code started working with PreferenceManager.getDefaultSharedPreferences().
What you want to do and what you are doing differs. If you just want to put default shared preference for a key then consider this example. If your whole activity has just one shared pref file then you need not specify any name. It will automatically get it.
public MainActivity extends AppCompatActivity {
SharedPreferences mPrefs;
int test;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_counter);
mPrefs = this.getPreferences(Context.MODE_PRIVATE);
test = mPrefs.getInt("pref_bt_select", 0);}
}
For the above example you can define the key and default value in your strings.xml and then you can refer to it while looking for the prefs you want.
Hey I have used AppCompat for my preference screen too.I did this because I wanted to use Vintage Chroma and this was the only way. But I am able to use PreferenceManager.getDefaultSharedPreference() without any errors.
Also if you want to use default shared preferences in the Fragment you can use :
SharedPreferences preferences = this.getActivity().getSharedPreferences("pref", Context.MODE_PRIVATE);
Here is my full code :
public class PreferencesActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new PreferencesScreen())
.commit();
ActionBar toolbar = getSupportActionBar();
if (toolbar != null) {
toolbar.setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
public static class PreferencesScreen extends PreferenceFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_xml);
}
}
}
Here is my code snippet for MAinActivity
Just the initial part where I set the default text theme.
`public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
AutoCompleteTextView mytextview;
public static String[] list;
ArrayList<String> recent = new ArrayList<String>();
public int recent_index = 0;
Menu mMenu;
#Override
protected void onCreate(Bundle savedInstanceState) {
/*Setting default theme.*/
SharedPreferences Sp= PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
int firstRun=Sp.getInt("firstRun",0);
if(firstRun==0)
{
SharedPreferences.Editor editor=Sp.edit();
editor.putInt("paragraphFontColor", Color.parseColor("#ffffff"));
editor.putInt("headingFontColor",Color.parseColor("#DE5246"));
editor.putInt("subheadingFontColor",Color.parseColor("#597d5e"));
editor.putInt("hyperlinksFontColor",Color.parseColor("#A5D8F5"));
editor.putInt("bodyColor",Color.parseColor("#2b2b2b"));
editor.putString("paragraphFont","PrintClearly.otf");
editor.putString("headingFont","PrintBold.otf");
editor.putString("subheadingFont","PrintBold.otf");
editor.putString("hyperlinkFont","PrintBold.otf");
editor.putString("paragraphFontStyle","normal");
editor.putString("headingFontStyle","normal");
editor.putString("subheadingFontStyle","normal");
editor.putString("hyperlinkFontStyle","normal");
editor.putString("actionBarColor","#597d5e");
editor.putString("paragraphFontSize","20px");
editor.putString("headingFontSize","30px");
editor.putString("subheadingFontSize","20px");
editor.putString("hyperlinkFontSize","20px");
editor.putString("firstRun",0);
editor.commit();
}
`
So I am trying to implement a preferences menu in my app. I used the standard generated template in android studio. THe issue is that now I can't figure out how save the values the user specifies. I thought about using a click listener to determine when a user clicked a checkbox and then getting the actual value of the checkbox and saving that to sharedpreferences, but I can't figure out how to do it.
Does anyone have any suggestions on how use onClick in a preference activity?
OK, we seem to be on the right track about the system storing the values automatically, but whenever I try to reference them from my main class, it always returns null. Here is my code:
boolean trueorfalse = PreferenceManager.getDefaultSharedPreferences(getActivity())
.getBoolean("my_key", false)
;
So I assume you've already defined your Preferences in res --> xml and it looks something like this:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="my_key"
android:summary="#string/desc_string"
android:title="#string/title_string" />
</PreferenceScreen>
As soon as the user checks or unchecks the CheckBox the systen will automatically create an entry in the default Preference-file which you can access like this:
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("my_key", false);
But back to your initial question: If you want to assign an onClick-Listener to your preference you have to do something like this:
Preference myPreference = (Preference) findPreference("my_key");
myPreference .setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
// do something
}
});
Note: In this example it isn't a CheckBoxPreference, it's just a simple Preference
I tried the same in my SettingsMenu by implementing OnSharedPreferenceChangeListener
public class SettingsMenu extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
Context context = getApplicationContext();
SharedPreferences menu_settings = PreferenceManager.getDefaultSharedPreferences(context);
menu_settings.registerOnSharedPreferenceChangeListener(this);
...
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// check the checkboxes
}
}
Hope it helps :)
I have a PreferenceFragment where I have defined a CheckBoxPreference in XML. I need to check this value in a Service, but it always gives me the old value. I noticed the value is correctly changed when I restart the application.
My Preference Fragment :
public class OptionsFragment extends PreferenceFragment
{
public static final String WIFI_ONLY = "wifi";
private SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MyApplication.getInstance());
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.config);
}
}
My config.xml :
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:defaultValue="true"
android:key="wifi"
android:summary="Check if you want to use wifi only"
android:title="Use Wifi only" />
</PreferenceScreen>
My Service :
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MyApplication.getInstance());
Log.d(TAG, "isWifiOnly : "+settings.getBoolean(OptionsFragment.WIFI_ONLY, true));
The log always return the same value no matter if I change it or not, except if i restart the app. Also, in my MainActivity I have that line in OnCreate():
PreferenceManager.setDefaultValues(getApplicationContext(), R.xml.config, false);
It creates the config file with the default value if needed.
I'm doing something wrong, the question is what ?
I found a solution thanks to this link Managing SharedPreferences in both PreferenceActivity and Service within same app and thanks to Andrew T. :
The issue was the multi process mode. If you have a Service which is declared in the manifest with a android:process="" (which is my case) then it's necessary to set a multi process mode.
Here is what i did :
in PreferenceFragment :
public static final String CONFIG_NAME = "pref";
...
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName(CONFIG_NAME);
getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
addPreferencesFromResource(R.xml.config);
...
}
My Service :
SharedPreferences settings = MyApplication.getInstance().getSharedPreferences(OptionsFragment.CONFIG_NAME, Context.MODE_MULTI_PROCESS);
and I set the default values in MainActivity this way :
PreferenceManager.setDefaultValues(getApplicationContext(), OptionsFragment.CONFIG_NAME, Context.MODE_MULTI_PROCESS, R.xml.config, false);
And now it works fine. Hope it will help !
Thank you again Andrew T.
I had the same issue for the last days...
I have a preference.xml with my layout and keys and inflate it into a PreferenceFragment while Listening on changes and thereby informing a Service of my Application of any change.
The crucial part is to set the mode of the SharedPreference access right:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
}
The Context.MODE_MULTI_PROCESS flag makes commits() apply to all accessing processes so even my Service would get direct access to the just changed values.
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
if(SettingsManager.setupIsValid(getActivity())){
Intent startServiceIntent = new Intent(getActivity(), IntentService.class);
startServiceIntent.setAction("PREFERENCES_CHANGED");
getActivity().startService(startServiceIntent);
} else {
Toast.makeText(getActivity(), getString(R.string.settings_incomplete), Toast.LENGTH_SHORT).show();
}
}
This will first do check magic and whenever the settings are valid inform the service of the change.
This allows the usage of multiple processes and always current preference values across all processes.
P.S.: direct access then looks like this
SharedPreferences prefs = context.getSharedPreferences(context.getPackageName() + "_preferences", Context.MODE_MULTI_PROCESS);
I'm writing an android app with a preferencesActivity in which selections made in my instance of preferencesActivity affect the values of other preferences items displayed. While I'm able to change the values of the underlying SharedPreferences items pogrammatically, those changed values aren't reflected in the displayed list items until I exit my preferencesActivity and reload it. Below is a stripped down version of my settings class and xml file which illustrate the problem. If a user sets Guitar as the value for the preference with the key instrumentList, I'd like the preference with key tuningChoice to revert to Standard.
//necessary import declarations go here
public class Settings extends PreferenceActivity implements OnSharedPreferenceChangeListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
SharedPreferences app_preferences = PreferenceManager.getDefaultSharedPreferences(this);
app_preferences.registerOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged (SharedPreferences sharedPreferences, String key) {
Log.d("onSharedPreferencesChanged", "sharedPreferences changed. key: " + key);
Editor preferencesMod = sharedPreferences.edit();
String instrumentChoice = sharedPreferences.getString("instrumentList", "Guitar");
if(key.equals("instrumentList")) {
Log.d("Settings", "key is instrumentList. chooseTuning before if: " + sharedPreferences.getString("chooseTuning", "no luck"));
if(instrumentChoice.equals("Guitar")) {
preferencesMod.putString("chooseTuning", "Standard");
preferencesMod.commit();
Log.d("Settings", "chooseTuning after if: " + sharedPreferences.getString("chooseTuning", "ciao"));
}
}
}
}
xml file preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="Settings">
<ListPreference android:title="Choose an Instrument" android:key="instrumentList" android:entryValues="#array/instruments" android:entries="#array/instruments"/>
<ListPreference android:title="Choose Tuning" android:key="chooseTuning" android:entryValues="#array/tuningChoices" android:entries="#array/tuningChoices" android:persistent="true"/>
</PreferenceScreen>
I can call addPreferencesFromResource again in my onSharedPreferenceChanged method and that loads a duplicate of all the preferences items, displayed below the old items, with the correct values. If I could figure out some way to cancel out the initial addPreferencesFromResource called during onCreate, I guess I would be set.
Any help would be appreciated, Thanks
I do something along these lines...hopefully it helps:
ListPreference list = (ListPreference) getPreferenceManager().findPreference("myList");
list.setValue(sharedPrefs.getString("myList", "default"));
list.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
sharedPrefs.put("myList", newValue.toString());
return true;
}
});
You need to prevent addPReferencesFromResource from running twice? Is this loading your default values? If so, add an additional SharedPreference called DEFAULTS_LOADED and read its value in on create like: (WARNING PSUEDO CODE):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences app_preferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean loadDefaults = app_preferences.getBoolean(DEFAULTS_LOADED, true);
if(loadDefaults)
{
addPreferencesFromResource(R.xml.preferences);
Editor editor = app_preferences.edit();
editor.putBoolean(DEFAULTS_LOADED, true);
editor.commit();
}
app_preferences.registerOnSharedPreferenceChangeListener(this);
}
This will prevent you defaults from being written to the shared preferences every time your activity starts. I assume this is at least a portion of your issue.
If anyone comes to this problem, this is the solution:
ListView list = preferenceActivity.getListView();
list.performItemClick(list, 1, list.getItemIdAtPosition(1));
Maybe I am too late for answering this. But, I hope this might help beginner like me.
PackageInfo packageInfo = null;
try {
packageInfo = preference.getContext().getPackageManager().getPackageInfo(preference.getContext().getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
preference.setSummary(packageInfo.versionName);