Can't get simple PreferenceFragment example to work - android

I'm struggling with using PreferenceFragments, can't seem to get it to work.
I have one preferences file, named at.package.preferences (without GUI) to save internal values - this works.
Now I wan't to create a preference screen for other (public) settings for the user, but here's where I fail.
My code:
public class ChartPreferences extends Activity {
private SharedPreferences prefs;
private Button btn;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chart_preferences);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
btn = (Button) findViewById(R.id.button1);
getFragmentManager().beginTransaction().replace(R.id.prefs_chart_content,
new ChartPrefsFragment()).commit();
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(ChartPreferences.this, getLineSize(), Toast.LENGTH_SHORT).show();
}
});
}
public int getLineSize()
{
return Integer.valueOf(prefs.getString(getString(R.string.line_size_key), Helper.PREF_DEFAULT_LINE_SIZE));
}
public static class ChartPrefsFragment extends PreferenceFragment
{
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.chart_prefs);
}
}
}
So the preference screen shows and when I select a value, let's say 5, from the preference list, it's also ok. When I open the preferences list again, the 5 is still selected (so the preferences get saved - somewhere...)
Now the problem occurs in the getLineSize() function, when I try to access the saved value. It gives me a android.content.res.Resources$NotFoundException.
I don't know where the values of the PreferenceScreen get saved, but it seems like it is not in the defaultSharedPreferences (?)
Here's my chart_prefs.xml, just in case:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="#string/chart" android:summary="#string/chart">
<ListPreference android:entries="#array/prefs_line_size" android:title="#string/line_size" android:summary="#string/line_size" android:key="#string/line_size_key" android:entryValues="#array/prefs_line_size"/>
</PreferenceCategory>
</PreferenceScreen>

It seems pretty weird to be using android:key="#string/line_size_key", ie the name of your preference is a resource lookup. I haven't looked at the code for Preference but perhaps it doesn't resolve the string but just uses '#string/line_size_key' as the token under which the preference is saved.
You don't really want the name of your preference to be a resource lookup do you? It means the preference would disappear as the user changed languages on their device.

Related

Handling clicks in PreferenceActivity

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 :)

Default Shared Preferences give me wrong values in Service

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

Enable and disable option in PreferenceActivity

I am new to creating PreferenceActivity. My question is how to enable and disable option in preference screen by changing other preference?
My prefs.xml:
<ListPreference
android:entries="#array/units"
android:entryValues="#array/lunits"
android:key="listUnits"
android:summary="Units schosssing"
android:title="Units" android:defaultValue="C"/>
<ListPreference
android:entries="#array/palette"
android:entryValues="#array/lpalette"
android:key="listpalette"
android:summary="Palette schosssing"
android:title="Palette"
android:defaultValue="1"/>
In the listUnits there are 2 options, Celsius and Fahrenheit, so if user selects Celsius the listpalette should get enabled, and if user selects Fahrenheit becomes disabled, how can I do this?
My settings activity:
public class SettingsActivity extends PreferenceActivity
{
#Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
}
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
}
This code may be useful to you. Can take as reference.
First take instance of both of the ListPreference and apply this method.
ListPreference mlistUnits, mlistPalette;
mlistUnits= (ListPreference)findPreference("listUnits");
mlistPalette= (ListPreference)findPreference("listpalette");
mlistUnits.setEnable(false);
mlistPalette.setEnabled(true);
and use below listner
OnPreferenceChangeListener listener = new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// newValue is the value you choose
return false;
}
};
apply listener to ListPreference
mlistPalette.setOnPreferenceChangeListener(listener);
Firstly you can set default value for your listUnits listpreference to celcius or Fahrenheit ,according this you can make enable-disable your second listpreference.
Now when changing your Preference by selecting anyone of them you can follow below procedure.
1) implement OnSharedPreferenceChangeListener in your MyPreferenceFragment class and override the method onSharedPreferenceChanged
2) Code like below in your method
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// TODO Auto-generated method stub
if (key.equals("listUnits")) {
final String value = sharedPreferences.getString(key, "");
Preference Pref_cec=findPreference("listpalette");
if (value.equals("celcius")) {
wallpaperPref_admin.setEnabled(true);
}else{
wallpaperPref_admin.setEnabled(false);
}
}
}
Hope it will Help. Let me know if anything missing in my post.
As your second list is evaluated on basic of first list, what you may do
Look for preference click on the First list, get the value of preference clicked.
Using this value simply enable/disable your second list.

I am unable to get Shared Preferences of other application

I am new to Android.I am trying access SharedPreferences of one application in another application.
But i am not getting those values.
My code was posted below.
Create.java in SharedPref1
package com.example.sharedpref1;
public class Create extends Activity implements OnClickListener{
EditText et1,et2;
Button btn;
String LogID,Pwd;
public SharedPreferences loginDetails;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.create);
et1 = (EditText)findViewById(R.id.etC1);
et2 = (EditText)findViewById(R.id.etC2);
btn = (Button)findViewById(R.id.bCreate);
loginDetails = getSharedPreferences("logid", MODE_WORLD_READABLE);
btn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.bCreate)
{
LogID = et1.getText().toString();
Pwd = et2.getText().toString();
Toast.makeText(getApplicationContext(), "User Profile Createad With\nUser ID: "+LogID +"\nPassword: "+Pwd, Toast.LENGTH_LONG).show();
SharedPreferences.Editor store = loginDetails.edit();
store.putString("logid", LogID);
store.putString("pass", Pwd);
store.commit();
finish();
}
}
}
Show.java in SharedPref2
package com.example.sharedpref2;
public class Show extends Activity implements OnClickListener{
EditText log,pwd;
Button back;
public SharedPreferences loginDetails;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.show);
log = (EditText)findViewById(R.id.etid);
pwd = (EditText)findViewById(R.id.etPwd);
back = (Button)findViewById(R.id.bBack);
back.setOnClickListener(this);
loginDetails = getSharedPreferences("logid", MODE_WORLD_READABLE);
log.setText(loginDetails.getString("logid", "defValue"));
pwd.setText(loginDetails.getString("pass", "defValue"));
}
}
I am getting values as below
I am trying access SharedPreferences of one application in another application.
This is a bad idea. Quoting the documentation for MODE_MULTI_PROCESS:
SharedPreference loading flag: when set, the file on disk will be checked for modification even if the shared preferences instance is already loaded in this process. This behavior is sometimes desired in cases where the application has multiple processes, all writing to the same SharedPreferences file. Generally there are better forms of communication between processes, though.
(emphasis added)
Moreover, the only way this could possibly work is if you make the SharedPreferences MODE_WORLD_READABLE, which means any app can get to those preferences. Programmers with talent would not do this, but would use other IPC mechanisms that would limit the communications to between the two applications and only with user permission, so as to not leak user data to others.
Finally, you do not have any code that will work across processes. getSharedPreferences() will get preferences for your own process. The only way I can think of to get a SharedPreferences from another process would require calling getSharedPreferences() on a Context created via createPackageContext(), and I haven't tried this, as I wouldn't dream of implementing what you are proposing.
If you need to share content between applications I would suggest using a content provider and not SharedPrefrences. In my experience SharedPrefernces is unreliable in these situations.
MODE_WORLD_READABLE is depracated in API level 17.
http://developer.android.com/reference/android/content/Context.html#MODE_WORLD_READABLE

Custom Shared Preferences Android

I have set the Preferences in xml and I have the folowing Activity:
public class Preferencias extends PreferenceActivity {
//SharedPreferences prefs;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
setContentView(R.layout.preferences);
Button bt=(Button)findViewById(R.id.selectPic);
TextView tv=(TextView) findViewById(R.id.textView1);
String def=getResources().getString(R.string.noDefinido);
tv.setText(PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("logo", def));
bt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName(getApplicationContext(),
SDCardImagesActivity.class.getName());
startActivity(intent);
}
});
//habra que sacarlo de la red
String [] ofis ={"Venus", "Europa"};
ListPreference lp=new ListPreference(this);
lp.setValue("oficina");
lp.setEntries(ofis);
lp.setEntryValues(ofis);
lp.setTitle(R.string.oficina);
lp.setDefaultValue(ofis[1]);
getPreferenceScreen().addPreference(lp);
}
}
It works fine with the xml preferences but I also need to add a preference in code the reason of it is that the options of this ListPreference will come from the database (here I have the String array for now). The problem is the data changed for this preference is not persisted. When I make the changes I press back button I come back the value goes back to default value. How could I make sure this preference is saved too?
Thanks a lot
solved I included the preference without setting up its data then in code:
String [] ofis ={"Venus", "Europa"};
ListPreference lp=(ListPreference) getPreferenceManager().findPreference("oficina");
lp.setEntries(ofis);
lp.setEntryValues(ofis);
lp.setDefaultValue(ofis[1]);
works fine now

Categories

Resources