I am writing a code to the app execute a function only once. The problem that the getSharedPreference always return false (see first line) even if I close and open the application.
boolean firstboot = context.getSharedPreferences("BOOT_PREF",context.MODE_PRIVATE).getBoolean("firstboot", true);
if(firstboot)
{
context.getSharedPreferences("BOOT_PREF",context.MODE_PRIVATE).edit().putBoolean("firstboot", false).commit();
Log.d(TAG, "first" );
}
else
Log.d(TAG, "not first time" );
What I am doing wrong?
Best regards
If you open and close the application the preferences won't change, that's the whole point of shared preferences, think of it as a simple database that stores unique information.
If you want to reset the shared preferences you can either: uninstall and reinstall the application, force close the application and clear all data or add the code to clear it:
context.getSharedPreferences("BOOT_PREF", context.MODE_PRIVATE).edit().clear().commit();
Related
I've been testing out a few sample weather app code projects looking for a 3 to 5 day forecast one that easily compiles in android studio. I can't find a simple one that is at my level of understanding yet but working with one that might help. (If anyone knows of a simple up to date weather forecast app then note it below please)
First line in question.
if (getSharedPreferences(KEY_PREF, 0).getBoolean(KEY_PREF, true)
&& servicesConnected())
From:
private static final String KEY_PREF = "firstrun";
if (getSharedPreferences(KEY_PREF, 0).getBoolean(KEY_PREF, true)
&& servicesConnected()) {
if (getSharedPreferences(KEY_PREF, 0).getBoolean(KEY_PREF, true)
&& servicesConnected()) {
// get current city lat lon
buildGoogleApiClient();
mClient.connect();
CommonUtils.showToast("Retrieving your current location...");
// this will be done one time only
getSharedPreferences(KEY_PREF, 0).edit()
.putBoolean(KEY_PREF, false).apply();
} else if (savedInstanceState == null) {
if (DBHelper.getInstance().getCityCount() == 0) {
// called only if the cities array is empty too add a city
getSupportFragmentManager()
.beginTransaction()
.add(R.id.container, new AddCityFragment(),
AddCityFragment.class.getSimpleName()).commit();
} else {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new WeatherFragment()).commit();
}
}
}
According to developer.android.com
boolean getBoolean (String key, boolean defValue)
Parameters: (1) String key: The name of the preference to retrieve. (2) defValue boolean: Value to return if this preference does not exist.
My original questions asked:
What exactly is getBoolean doing?
The documentation doesn't say what mode 0 means in the 2nd parameter of getSharedPreferences (String name, int mode). Any idea what?
How can I add a watch for getSharedPreferences to Android Studio's debugging
The Solution that I deduced with the help of you guys:
getSharedPreferences(KEY_PREF, 0) is looking for a KEY_PREF preference file on the android device. It returns an object to it which allows us to use getBoolean to determine if there is a key inside it with the same name. In this case it was looking for a "firstrun" file which doesn't exist during first run of the app on the actual android devices storage (saved as cache). Since the key didn't exist on the first run it sets the boolean value as true and continues running inside the if statement. If the key "firstrun" existed and it was set to false then it would return false and skip executing inside that part of the if statement.
Mode 0 is MODE_PRIVATE = the default mode, where the created file can only be accessed by the calling application (or all applications sharing the same user ID).
When I was trying to debug the issue I noticed that I can add a debugger watch for getSharedPreferences(KEY_PREF, 0) and drill inside the resulting preference file from withing the debugger to see that the mMap parameter to the SharedPreferences object creates a "firstrun" key with the value of "false". It was a first for me to see how it adds this value.
I also found a cool plug-in for android studio for mac and windows which is faster than going into the android device or virtual device and clearing the apps cache. It's called ADB idea and used with the CTRL+ALT+SHIFT+A hotkey combo.
Thanks everyone!
SharedPreference is just a way to store some small-size data.
1) Meaning why would it return true if it doesn't exist?
You can have it return false if you want. That's just the default value for that key. You should set default to true/false depending on the data logic. For their particular case, setting the default true for that key goes with their app logic.
For example, AFAIK android sdk doesn't provide us with any apis that would say that app is running for the first time. So, to know that if the app is running for the first time or not, you could get the boolean value for a key like "is_first_run" and have the default value be true. If the app is run for the first time, then this value would not exist in shared preference because you've not set it yet. So, the default value true makes sense. And if you find it to be true then set it to false, so that the next time the app is run, it'll return false. If you clear the cache, the value will be true once again because the cache is destroyed and the variable no longer exists.
2) question what is operating mode 0 for SharedPreferences getSharedPreferences (String name, int mode)
Operating mode 0 is just the PRIVATE_MODE. The developer should have used the variable instead of just setting it to zero. Their are multiple modes for the sharedpreference. You can look into the docs for more. Private mode means that this data can be accessed by this application only.
3) How can I add a watch for getSharedPreferences (Where is it stored?)
Not sure what you mean by adding a watch. Are you talking about an event listener on the sharedPreference? AFAIK, you can't do that. Also, shared preference is stored in app's cache directory which can be /data/app/appname/cache or something else (idk for sure)
Shared Preferences store data till you delete and reinstall the app
getBoolean( "this is the key" , true);
if getBoolean returns null then this whole statement evaluates to true
If getBoolean( "this is the key" , false);
This means that if it returns null then evaluate it to false
Meaning why would it return true if it doesn't exist?
This was your question right ?
It is the coder's choice to make it true or false like
At first when user has logged in when you did not even touch sharedPreferences
then it would probably return the second argument
like
if(SharedPreferences.getBoolean('isUserOld' , true)){
Toast.make( Context , "Welcome to Our App" , Long).show()
}
Here it is checking whether user is old or not
If user is not old then if blocks gets executed because the second param returns true
And this indicates that a new user has logged in
How can I know if the user has ever used my Android app on this device
before?
You can create these methods to manipulate SharedPreferences:
Keep in mind, there is no way to stop the user from clearing the app data and therefore deleting the SharedPreference.
public boolean hasUsed()
{
SharedPreferences sp = getSharedPreferences("hasUsed",0);
boolean b = sp.getBoolean("hasUsed",false); // default value is false
return b;
}
public void writeUsed(boolean b)
{
SharedPreferences.Editor editor = getSharedPreferences("hasUsed",0).edit();
editor.putBoolean("hasUsed", b).commit();
}
Call them like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if user hasn't used the app, write to the preference that they have.
if (!hasUsed()) writeUsed(true);
// later in code:
if (hasUsed()) // if the user has used the app
{
// do something
}
}
Links for explanation of code:
How to store User name and password details in strings.xml
How to save app settings?
How to keep information about an app in Android?
If you store anything regarding it in your app,user is Owner of his device . he can clear it anytime.
Kindly store this information on either your server or use some analytics integration.
But I would prefer to store on server because in your case,analytics might be overhead for you as you just want to identify the existing users.
Explaination:
When your app starts, send device's unique id to your server, so that when user starts the app for next time,it will again send unique id and at that time your server can perform check in database for existance of recently received unique id.
In such a manner you can identify that the user has already used your app or not and then you can modify your business logic accordingly.
I hope it will be helpful !!
Check this : The Google Analytics SDK for Android makes it easy for native Android developers to collect user engagement data from their applications.
You can do things like :
The number of active users are using their applications.
From where in the world the application is being used.
Adoption and usage of specific features.
Crashes and exceptions.
In-app purchases and transactions.
https://developers.google.com/analytics/devguides/collection/android/
You can create a shared preference and can update a count value every time the user opens the app, like
SharedPreferences myPrefs = this.getSharedPreferences("myPrefs", MODE_WORLD_READABLE);
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putString("Count",Integer.valueof(myPrefs.getString("Count", null))+1) );
the code may have errors but the logic is right
When an automatic update occurs, the old date save in the preferences for my app gets delete.
How can i prevent this deletion?
I want that when my app auto updates , it does not delete my old data saved.
I am not sure whether this will be a good solution but just a suggestion you can try.
step 1: whenever you changeg (add/edit/remove) your data store it in permanent storage, you may try any of the following
a. save the data in file in sd card
b. store the data to your remote server or
c. store in internal memory of the phone.
(I am not sure whether it will persists after update at case c, for reference can check here
Step 2: creae a BroadcastReceiver that listens to the ACTION_PACKAGE_REPLACED Intent. So you know when your application package is updated. NOw read the data again from the storage where you saved the data ( either 1a/1b/1c)
Caution: It is not a good thing to save user data without his concern.
Android save your SharedPreference under /data/data/your package name/shared_prefs
Generally, update application won't delete your sharedPreference.
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
String installerPackageName, PackageInstalledInfo res) {
...
// First delete the existing package while retaining the data directory
if (!deletePackageLI(pkgName, null, true, PackageManager.DELETE_KEEP_DATA,
res.removedInfo, true)) {
// If the existing package wasn't successfully deleted
res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
deletedPkg = false;
} else {
....
}
....
}
I think you need to check the following:
Is your device a rooted device? Apps on a rooted device can delete anything they want.
Did you use a different package name in that updated apk?
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
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