I'm currently using a Parser and it parses every time the onCreate gets called.
My parser uses an XML file that's located in my assetfolder.
Is there any chance that I can make it parse only once, instead of every time I rotate the screen or restart the application?
Thank you :)
There are 2 answers to this question. The easy one first:
If you only want this to happen once, create a static boolean in your main activity and set it to true when the XML is parsed in. Then use:
if(!isParsed)
XML.parse();
The more complete answer to this question is to make sure you are handling configuration changes correctly.
I suggest you read this article on how to implement configuration change handling. You should be able to solve this problem "the Android way" by implementing this.
Hope this helps!
Persist a flag using the Preferences system the first time you complete a parse, and check this each time before parsing again. Do all this in your OnCreate() method.
SharedPreferences settings = getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
if (!settings.getBoolean("parsed", false)) {
parseTheXML();
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("parsed", true);
editor.commit();
}
There are other ways but this has the advantage of working across app reloads/phone power cycles - assuming that's what you want.
You could add a preference. Something like -
void setIsAppOpened() {
editor.putBoolean(APP_OPENED, true);
editor.commit();
}
Set it in your onCreate(). Then, also add the following code to check if the preference exists.
if (!prefs.contains(APP_OPENED))
{
//parse the XML
setIsAppOpened();
}
You can parse your XML in a "Application" object and have it accessible from there. Check out the documentation at http://developer.android.com/reference/android/app/Application.html
Related
I have a problem with the SharedPreferences If I want to save two different values. I tried with this code:
SharedPreferences sharedPref = getSherlockActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.SavedStartSilentHour), hour);
editor.commit();
editor.putInt(getString(R.string.SavedStartSilentMinute), min);
editor.commit();
// One editor.commit() is enough
If I run this code the first value is overwritten with the seccond value. If I delte the second part the value is saved correctly. Why is that?
Your code seems perfect!
You could simplify the thing by committing all the stuff after all the "puts" operations. Although I don't think that this could be your problem...
Just make sure SavedStartSilentHour and SavedStartSilentMinutes xml's defined values are correctly defined, i.e., if they are the same of course they will be overwritten. (This is the only one thing that makes any sense to me considering your code).
Let mew know of your progress ;)
Remove first call to
editor.commit();
and you will be fine.
The issue is most likely caused by re-using a key such that the second assignment simply overwrites the same-keyed value.
One way to test this hypothesis is to try using simple keys which eliminate such possibility, e.g.:
editor.putInt("hour", hour);
editor.putInt("min", min);
Alternatively, a debugger can be attached and the results of getString(keyId) can be compared.
If this does indeed "fix" the issue, then ensure that the SavedStartSilentHour and SavedStartSilentMinute resources actually evaluate to different strings - inspect the resource file itself.
When I originally wrote and published my app, I was using a custom written activity to handle application settings. I used custom file name to store shared preferfences, like this:
getSharedPreferences("custom_settings_file",MODE_PRIVATE);
But now I'm refactoring my app and I would like to implement PreferenceActivity or PreferenceFragment and an xml file with PreferenceScreen section. Every tutorial or example that I've seen is using
getDefaultSharedPreferences(context);
to retrieve shared preferences, because PreferenceActivity assumes default filename to store preferences and there's no way to tell it to use a different one(at least I couldn't find one after an hour of searching and reading documentation).
So now I have a problem. If I just simply use the new default file, existing users of my app will lose their settings when they update the app, because the new application will not know anything about "custom_settings_file". What would be the best way to move the data from an old file to a new one on app update?
Here are the possible options that I could come up with:
Extend Application class and implement a piece of code in onCreate() so that every time my app is launched, it would check for existence of "custom_settings_file" and move it's contents to the new one. But running a block of code on every app launch seems like wasting too much processing resources for an operation that only needs to run once.
Just notify the user that their old settings are gone. But obviously this is not acceptable.
Is there a better solution, than option 1? Perhaps someone has already faced a similar problem?
What is preventing you from doing number 1 only once?
Just add a "migration" boolean to the new sharedpreferences.
If you also load the xml preference file then you can try this:
PreferenceManager.setDefaultValues(context, YOUR_PREFERENCE_NAME, MODE_PRIVATE, R.xml.preference_file, false);
If not (you want to add each preference item dynamically in your code) then you can do like this:
PreferenceManager pm = getPreferenceManager();
pm.setSharedPreferencesMode(MODE_PRIVATE);
pm.setSharedPreferencesName(YOUR_PREFERENCE_NAME);
In case you still want to use the defaultSharedPreference and process the migration then ... I'm writing this and I see Nicklas's answer, so I'm done here.
Could you add value in your new SharedPreferences that records whether you are a new install or an upgrade. If you don't have the setting in your sharedpreferences, check to see if you have an old preferences file in the way you were before. Then convert those preferences to your new method, and set your private setting indicating that it's been upgraded. Then just set the new value indicating the new state and you won't need to check your old preferences any more.
Android Guide recommends defining preferences in XML files, And from there, these can be loaded in PreferenceActivity/PreferenceFragment etc for viewing and editing by user. But in real scenario, User Interacts with other activities first, then (maybe) with Preferences UI.
What if the starter activity needs some of these preferences ? They'll be not loaded yet, because preferences resources has not been inflated yet. Is there a way to pre-access preferences in XML files ?
Yes. When you first request the preference you can provide it with a default value. E.g. if you are loading a preference of type Int, then you can do so in the following manner from an activity:
SharedPreferences defaultSettings = PreferenceManager.getDefaultSharedPreferences(this);
int preferenceValue = defaultSettings.getInt("PreferenceName", 7);
This would load your preferenceValue to be 7 (without this preference ever being initialized yet). This is assuming that in your XML preference file, you have a preference of key "PreferenceName". If you plan on editing this preference in the activity before the Preference activity has been ran, be sure you commit your changes with a SharedPreferenceEditor:
// ... change to preferenceValue occurs prior to this code
SharedPreferences.Editor defaultEditor = defaultSettings.edit();
defaultEditor.putInt("PreferenceName", preferenceValue);
defaultEditor.commit();
We probably want to avoid "PreferenceName" in a hardcoded matter though, and instead use it as a string in the strings.xml file. This way it can be grabbed both from the initial code when the preference has not been saved yet and from the Preference XML file as well. This means that our above code would substitute the string "PreferenceName" with something like the following:
getResources().getString(R.string.pref_name)
And in your Preference XML file you may would reference the key in the following way:
android:key="#string/pref_name"
android:defaultValue="7"
This should cover "pre-loading" the preference as well as trying to keep most of the application settings within one place. There may indeed be overlap in terms of whether or not the XML preference was created/loaded before the initial Activity occurred, but I haven't tested that out yet.
EDIT: It turns out instead of using the above code, you can directly load the XML file (with its default preference) by the following method:
PreferenceManager.setDefaultValues(this, R.xml.preference, false);
More information about this method can be found in the documentation for the PreferenceManager: http://developer.android.com/reference/android/preference/PreferenceManager.html
If you look at SharedPreference API, you will see this
getString(String key, String defValue)
So, you can actually in fact define a default value if it's not already existed.
Source: http://developer.android.com/reference/android/content/SharedPreferences.html
You can also predefine default value in XML using
android:defaultValue="SOMETHING"
I just implemented a preferences screen for one of the sample apps that I am creating. I followed the guide given on google site. All is fine and I loaded up a ListPreference and I am able to store it and persist it also. There is also one minor problem here. I have already defined a custom preference file for the app but this automatic handling of the preference screeen seems to be creating a preference file on its own. For now I was trying to get this code to work but it is not getting the custom preference file.
final Preference customPrefs = getPreferenceScreen().findPreference(Utils.PREFS_NAME);
customPrefs.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
customPrefs.getEditor().commit();
return true;
}
});
Is there a way to bind the custom preference file with this auto preference class in anyway ?
You can set a custom name for the file used to store the preferences, used in your PreferenceActivity, by calling its getPreferenceManager().setSharedPreferencesName("file_name") method. Just remember that you need to set that before calling addPreferencesFromResource, otherwise your UI will still change stuff back to the wrong file (the default one).
As I said, you don't need to do that, since you can use the default file provided by the system. If/when you need to read the preferences elsewhere, you can then just call PreferenceManager.getDefaultSharedPreferences(Context context).
I already addressed those remarks in another question.
Also remember that some of the methods are deprecated. If you're writing new code, try to avoid them and conform to the new "Fragment Way" of doing things.
I would like to know if and how it is possible to detect if my application have run in the past on a given android device. I would like every time the phone reboots to be able to check if my application has run on the past and retrieve some private data. If not just create those data.
You could store a simple value in the SharedPreference of the application.
insert this into your onCreate() in your Main Activity
SharedPreferences shared = getSharedPreferences("config", 0);
if (shared.getBoolean("hasRunBefore", false))
{
// have run before.
}
else
{
SharedPreferences.Editor editor = shared.edit();
editor.putBoolean("hasRunBefore", true);
editor.commit();
// have not run before
}
As others have said, the easiest way to read and write this information is in the SharedPreferences. However, you said you want to do this every time the phone reboots. The way to go about that is to implement a BroadcastReceiver and register to receive ACTION_BOOT_COMPLETED message, and make sure to add a permission to your manifest for RECEIVE_BOOT_COMPLETED.
http://developer.android.com/guide/appendix/faq/commontasks.html#broadcastreceivers
http://developer.android.com/reference/android/content/Intent.html#ACTION_BOOT_COMPLETED
http://developer.android.com/reference/android/Manifest.permission.html#RECEIVE_BOOT_COMPLETED
Check if this data exists ? Or put something in the default PreferenceManager of your application
You'd save everything using SharedPreferences. This will create a file readable by your app that will be created when first written to.
See the following:
Tutorial
Documentation