Update EditTextPreference Summary on Post SyncTask - java

In my app once user provide three inputs, AsyncTask starts which connects to the server and gets info for two more fields. Once AsyncTask is finished, I want to set those two received values in opened setting page.
I searched and try this code, but not updating summary for fields for which value has fetched from server.
Problem is I'm not able to set values received from server as summary to EditTextPreference. If I reopen settngs page it shows value not without reopening.
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(key);
}
private void updatePreference(String key) {
if (key.equals("id")) {
Preference preference = findPreference(key);
if (preference instanceof EditTextPreference) {
EditTextPreference editTextPreference = (EditTextPreference) preference;
if (editTextPreference.getText().trim().length() > 0) {
editTextPreference.setSummary(editTextPreference.getText());
} else {
editTextPreference.setSummary("");
}
}
} else if (key.equals("sclass")) {
Preference preference = findPreference(key);
if (preference instanceof EditTextPreference) {
EditTextPreference editTextPreference = (EditTextPreference) preference;
if (editTextPreference.getText().trim().length() > 0) {
editTextPreference.setSummary(editTextPreference.getText());
} else {
editTextPreference.setSummary("");
}
}
}
}

Create a listener and call it in your onCreate
sharedPrefYourObj.registerOnSharedPreferenceChangeListener(t‌​his);
try to register you listener onResume and unregister it onPause though rather than onCreate!
example :
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}

Related

Want to attach a listener to a preference, what am I doing wrong here?

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key == " /*the key I want*/ ") {
//do stuff here
}
};
prefs.registerOnSharedPreferenceChangeListener(listener);
Also, I learned that preferences all get automatically saved to a default SharedPreferences file which you access through getDefaultSharedPreferences(). Does that happen when app is first run or does it wait until a user interacts with a preference?

How to create a Listener to Preferences changes in Preferences activity?

I have Preferences activity in my app that has ListPreference so the user can choose language for the app.
The app displays the new language just after the user close the Preferences activity.
I want to create a listener to the ListPreference so the app will restart when the Listener is triggers (just after the user choose a language/choose item from the ListPreference).
How can I do that?
SettingsActivity:
public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* 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 value) {
String stringValue = value.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 {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* #see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
setTitle(R.string.action_settings);
}
/**
* Set up the {#link android.app.ActionBar}, if the API is available.
*/
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
if (!super.onMenuItemSelected(featureId, item)) {
NavUtils.navigateUpFromSameTask(this);
}
return true;
}
return super.onMenuItemSelected(featureId, item);
}
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| GeneralPreferenceFragment.class.getName().equals(fragmentName);
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("example_text"));
bindPreferenceSummaryToValue(findPreference(getString(R.string.language_shared_pref_key)));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
getActivity().finish();
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
}
}
pref_general.xml:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:defaultValue="#string/language_code"
android:entries="#array/pref_languages_list_titles"
android:entryValues="#array/pref_languages_list_values"
android:key="#string/language_shared_pref_key"
android:negativeButtonText="#null"
android:positiveButtonText="#null"
android:title="#string/pref_title_language" />
</PreferenceScreen>
Thank you!!!
Here is some real quick sample code for a shared prefs chaneg listener I have set-up in one of my projects; it's located in the onCreate of a Service but obviously can detect changes to my shared prefs that originate from anywhere in my app.
private SharedPreferences.OnSharedPreferenceChangeListener listener;
//Loads Shared preferences
prefs = PreferenceManager.getDefaultSharedPreferences(this);
//Setup a shared preference listener for hpwAddress and restart transport
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals(/*key for shared pref you're listening for*/) {
//Do stuff; restart activity in your case
}
};
prefs.registerOnSharedPreferenceChangeListener(listener);
One possible solution is to keep everything together, and implement the OnSharedPreferenceChangeListener interface inside your own GeneralPreferenceFragment.
You can do that by declaring that GeneralPreferenceFragment both inherits from PreferenceFragment, and implements SharedPreferences.OnSharedPreferenceChangeListener interface. This means that you need to define override for onSharedPreferenceChanged in GeneralPreferenceFragment.
Because preferences can change only if the fragment in question is active, you can register your fragment as listener in onResume for a fragment (via registerOnSharedPreferenceChangeListener), and unregister it on onStop.
The following example code is in Kotlin, not in Java, but it should be fairly easy to translate it.
class SettingsActivity : AppCompatActivity() {
// ...
class SettingsFragment : PreferenceFragmentCompat(),
SharedPreferences.OnSharedPreferenceChangeListener
{
// ...
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?,
key: String?) {
if (key == "<something>")
// do something
}
override fun onResume() {
super.onResume()
preferenceScreen.sharedPreferences
?.registerOnSharedPreferenceChangeListener(this)
}
override fun onPause() {
super.onPause()
preferenceScreen.sharedPreferences
?.unregisterOnSharedPreferenceChangeListener(this)
}
}

How to retrieve preference data from the service

I m developing an android app.
The main activity is a preferencescreen
public class MainActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
my app contains also a service that start automatically when the android boot.
In the onStart() of my service class, I m trying to retrieve data saved by the user in the preferencescreen with the following code
public void onStart(Intent intent, int startId) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
get_prefrence_settings((Preference) preferences);
jniTask = new JniBackGround();
jniTask.execute(new String[] { "http://www.easycwmp.org" });
}
private void get_prefrence_settings(Preference p) {
if (p instanceof PreferenceGroup) {
PreferenceGroup pGrp = (PreferenceGroup) p;
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
get_prefrence_settings(pGrp.getPreference(i));
}
} else {
if (p instanceof ListPreference) {
ListPreference listPref = (ListPreference) p;
p.setSummary(listPref.getEntry());
client_interface = (String) listPref.getEntry();
}
if (p instanceof CheckBoxPreference) {
if (((TwoStatePreference) p).isChecked())
enable = "1";
}
if (p instanceof EditTextPreference) {
if (pref_key.equals("Time")) {
time = editTextPref.getText();
}
}
}
}
but I m getting a crash when my service start that indicate that:
android.app.SharedPreferencesImpl can not be cast to android.preference.Preference
How to retrieve the preference settings from my onStart() service without loading the MainActivity interface?
How to retrieve the preference settings from my onStart() service without loading the MainActivity interface?
Call getString(), getInt(), or related getter methods on the SharedPreferences object.

Does this snippet cause an infinite loop or other?

Only on old android devices (2.x) I've a crash caused by stackoverflow everytime I rotate emulator. If I comment "preferenze()" emulator does not crash but app does not keep new settings. Can this code create an infinite loop? Is a incorrect code? What should be to runs correctly? Thanks!
private boolean preferencesChanged;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
private void preferenze() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
CheckboxPreference = prefs.getBoolean("checkboxPref", true);
ListPreference = prefs.getString("listpref", "");
numeronotifiche = prefs.getString("notify", "");
Sound = prefs.getString("sound", "");
barranotifiche = prefs.getBoolean("keep", false);
natura = prefs.getBoolean("suoninaturasino", false);
snatura = prefs.getString("suoninaturascelta", "");
snaturaold = prefs.getString("snaturaoldvalue", "");
if (snaturaold != snatura){
stopService(new Intent(this, UnUsedService.class));
}
SharedPreferences prefs2 = getSharedPreferences(PRIVATE_PREF, 0);
Editor editor10 = prefs2.edit();
editor10.putString("snaturaoldvalue", snatura);
editor10.commit();
// suoni attivati (o no)
if (natura){
startService(new Intent(this, UnUsedService.class));
}
else {
stopService(new Intent(this, UnUsedService.class));
}
if (barranotifiche){
showNotification();
}
else {
cancelNotification();
}
GestioneAllarme alarm = new GestioneAllarme();
if (CheckboxPreference){
if (numeronotifiche.equals("3")){
alarm.CancelAlarm(this);
alarm.SetAlarm3(this);
}
else if (numeronotifiche.equals("1")){
alarm.CancelAlarm(this);
alarm.SetAlarm1(this);
}
else if (numeronotifiche.equals("2")){
alarm.CancelAlarm(this);
alarm.SetAlarm2(this);
}
else {
//
}
}
else {
//
GestioneAllarme alarm2 = new GestioneAllarme();
alarm2.CancelAlarm(this);
}
//
if (Sound.equals("")){
Sound = "2";
Editor editor = prefs.edit();
editor.putString("sound", "2");
editor.commit();
}
if (ListPreference.equals("")){
ListPreference = "1500";
Editor editor = prefs.edit();
editor.putString("listpref", "1500");
editor.putInt("indexfade", 1500);
editor.commit();
}
if (numeronotifiche.equals("")){
numeronotifiche = "2";
Editor editor = prefs.edit();
editor.putString("numeronotifiche", "2");
editor.commit();
}
fade = Integer.parseInt(ListPreference);
notify = Integer.parseInt(numeronotifiche);
if (fade == 500){
animazione = R.style.MyCustomTheme1;
fadein = R.anim.fadein500;
fadeout = R.anim.fadeout500;
}
else if (fade == 1000){
animazione = R.style.MyCustomTheme2;
fadein = R.anim.fadein1000;
fadeout = R.anim.fadeout1000;
}
else if (fade == 1500){
animazione = R.style.MyCustomTheme3;
fadein = R.anim.fadein1500;
fadeout = R.anim.fadeout1500;
}
else if (fade == 2000){
animazione = R.style.MyCustomTheme4;
fadein = R.anim.fadein2000;
fadeout = R.anim.fadeout2000;
#Override
protected void onResume() {
super.onResume();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
preferencesChanged = true;
}
};
sp.registerOnSharedPreferenceChangeListener(listener);
protected void onStop(){
super.onStop();
if(preferencesChanged){
//Update the app
preferenze();
}
}
public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.preferences);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String listpref) {
It seems that as soon as preferenze() always modify the shared preferences you will have an infinite loop.
Since you didn't post the complete code it's difficult to say. But I guess that your code is such that it always modify prefs only on android 2.x
you can try something like this to avoid infinite loop.
private boolean isPreferenzeRunning = false;
...
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String listpref) {
if(!isPreferenzeRunning)preferenze();
}
};
...
private void preferenze()
isPreferenzeRunning = true;
try{
...
}finally{isPreferenzeRunning = false;}
}
That code wouldn't even compile.
The code in preferenze() will return the preference values (boolean, String, int, etc), not the Preference objects. By changing the values in that method, you will also cause a StackOverflowError.
What is the need for a OnSharedPreferenceChangeListener?
// here several if/if else to change value
Those sentences probably change the Shared Preferences, that in turn will fire your listener, which in turn will call preferenze, ..., and so on. If this continues for ever, a S.O will be thrown. Now depending on the conditions it could happen that the preferenze method only reads but does not modify anything. In this case the loop will end.
And about the error being observed in 2.X devices only, it could be due to 4.x devices being more recent and probably having more RAM memory.
UPDATE:
The code is still incomplete. Looks like there are two activities: the one you posted first and the new one. I guess (that's all I can do with the code you posted) you have a PreferenceActivity to show the settings and allow the user to change them, and the listener is there to update other parts of the application according to the new settings. The problem is that when the listener is called, it itself modifies the settings, and this in turn will call the listener again, which will modify the preferences again, and so on. This will throw an SOException once the heap runs out of memory.
A way of rearranging the code to solve this would be:
Register the OnSharedPreferenceChangeListener in your activity's onResume instead of onCreate, and deregister it in the onPause method (calling unregisterOnSharedPreferenceChangeListener). Deregistering is very important because we don't want to listen for changes once the user leaves the screen, or the activity is recreated by the system (for instance when the device rotates):
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//We have removed the listener registration from here
}
#Override
protected void onResume() {
super.onResume();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String listpref) {
//I'll show what to do here in point 2.
}
};
sp.registerOnSharedPreferenceChangeListener(listener);
}
#Override
protected void onPause() {
super.onPause();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.unregisterOnSharedPreferenceChangeListener(listener);
}
With your current code, each time the user changes a single setting, the preferenze method is called to update the app. So if it changes 5 fields, the method is called 5 times. What we could do now is to check for changes just once. I assume you don't care how many fields the user has changed, since all you need is to know if there are changes or not. So in the listener, instead of calling preferenze, you could set a boolean flag to true:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
preferencesChanged = true;
}
Ok, so now we have a way of telling whether the settings have changed or not. When the user is done and the activity is about to be closed, the methods onPause, onStop and onDestroy will be called in this order. You can use one of these methods to check the boolean flag and only if there are changes, update the app. This way, if the user changes 1, 3 or 20 fields, we will update the app just once at the end. You can do this in any of the 3 thethods, but it's very important to do this AFTER deregistering the listener (onPause), or else you'll run into problems again. Example:
protected void onStop(){
super.onStop();
...
if(preferencesChanged){
//Update the app
preferenze();
}
}
You might need to change some things but overall you get the idea.

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