I have a SharedPreference that counts the amount of launches of my App. I expect this to be 0, when I install my app. Nevertheless it is 14. The same strange behaviour I observe with my database, that already exists on a fresh install.
I didn't intent to recycle my app data (like in the Google Cloud). On my device in the account settings the app-data sync is on. If I turn it off, and make a reinstall I observe the same behaviour.
Anyone has every observed such a behaviour? Is there any way to prevent recycling old data and force a proper install?
In Android Marshmallow Google introduced the "Auto Backup" feature which is turned on by default if your targetSdkVersion is >=23.
This will back up your database and SharedPreferences by default and restore it when you re-install the application. To turn this feature off you have to add android:allowBackup="false" to your AndroidManifest.xml.
More info here: Auto Backup for Apps
Review your code in AndroidManifest on tag application if it has android:allowBackup="false". If you don't have (by default it's true), your app participates on android backup and restore infrastructure and can happen exactly what you say.
More information in this post: What is "android:allowBackup"?
This needs to be handled from app side regarding shared Prefs.
Created a shared preference helper class and in the helper class have the below condition.
private static String SHARED_PREFS_VERSION = "SharedPrefsVersion"; // In this save the version of current shared Prefs.
void SharedPrefsHelper() {
if( BuildConfig.Version > getSharedPrefsVersion() ) {
SharedPreferences.Editor editor = prefs.edit(); editor.clear(); // Clear all the shared Prefs and update the current version.
SetSharedPrefsVersion(BuildConfig.Version);
}
}
For further reference look at :
https://stackoverflow.com/a/12381061/7364024
Related
I've recently discovered that Firebase Auth saves itself on the device even after my app is uninstalled. I can't figure out how to REMOVE this old Auth info.
I don't want a user to still be signed in after uninstalling and reinstalling the app. If for no other reason than my own testing of what I expect to be "clean installs" on the same device.
I understand there is no easy way to capture an uninstall event, so I want to clear out any potential old Auth info on the first launch.
So I added code (which seems to work fine) to check if this is the first launch:
Boolean firstRun = prefs.getBoolean("firstrun", true);
if (firstRun) {
// delete everything an old user could have left behind
// ==> This is where I need help <==
prefs.edit().putBoolean("firstrun", false).apply();
} else {
// move along, not the first launch
}
I've tried (unsuccessfully):
FirebaseAuth authData = FirebaseAuth.getInstance();
authData.signOut();
These calls also seem to be the advice in this related question for iOS, but I haven't been able to apply its wisdom:
Firebase - Deleting and reinstalling app does not un-authenticate a user
Even after calling signOut() the app keeps logging me in under the old account!
My "logout" button uses FirebaseAuth.getInstance().signOut(); and works. Is there something odd (possessed?) about this "old" Auth instance that is being saved after an uninstall that it just won't die?
Specifically when I uninstall and then install/run from Android Studio:
at first authData and currentUser both are not null
I call the above code, trying to get rid of this old user
3 millisecond later (immediately after I call that
code) they are still NOT NULL.
Another 2 milliseconds, currentUser IS NULL (yay?)
Another 71 milliseconds... still null (so far so good)
Just under a second later... I'M SIGNED IN AS THE OLD USER?! How is this possible?
In the Firebase Console under Authentication, this account is shown as last signed in 6 days ago. So it's not somehow getting re-signed-in.
Does anyone know how to remove FirebaseAuth data from a device? I don't want to "delete" the user account, just remove all traces of it from this device.
Oddly enough, the account I keep getting unwillfully logged in under isn't even the last account that logged into my app on this device. And this was never a problem in the past (hence my not even knowing that Firebase saved Auth after uninstall). So it looks like Auth info isn't always saved after uninstall... but when it happens it's impossible to remove?
Any help much appreciated!
Add android:allowBackup="false" in your <application> in manifest:
From the docs:
android:allowBackup
Whether to allow the application to participate in the backup and restore infrastructure. If this attribute is set to false, no backup or restore of the application will ever be performed, even by a full-system backup that would otherwise cause all application data to be saved via adb. The default value of this attribute is true.
Try also FirebaseAuth.getInstance().getCurrentUser().delete
Firebase stores auth info in shared preference with file names starting with "com.google.firebase.auth.api.". Therefor if you delete these files as part of your log off flow it would help the purpose.
public void clearFirebaseAuthInfo(Context ctx)
{
File dir = new File(ctx.getFilesDir().getParent() + "/shared_prefs/");
String[] children = dir.list();
for (int i = 0; i < children.length; i++)
{
if(children[i].contains("com.google.firebase.auth.api."))
{
new File(dir, children[i]).delete();
}
}
}
My login system uses SharedPreferences to store information about the user. The main two variables for the login system are:
loggedin - boolean
userID - int of the userID that's logged in (primary key on the DB)
When the user logs in, loggedin is set to 1 and the userID is set to the user ID fetched from the DB. When the logout button is pressed loggedin is set to 0 and userID set to null.
Situations:
I log in, close the app and repoen it = fine, still logged in to the correct account
I log in, then logout, close & reopen the app = fine, comes up with login screen
I carry out invalidate caches and restart in android studio = fine, stays logged in on the correct account.
Now here's the one that's going wrong: If I login, then uninstall the app off my phone and press run on android studio the app launches and logs in to a really old account that no longer exists on the DB; and I can't work out why this is happening.
My only thought is there is a userID stored on the device that isn't being removed, but that could be completely wrong. Any ideas?
I've added some log tags throughout the code and before the app is uninstalled the userID is correct and when it's been reinstalled it's the old one.
Shared Preferences are always cleared along with uninstalling app.
But since android-21 Backup task stores preferences by default to cloud. Later when you uninstall then install newer version .You are probably going to use restored preferences. To avoid that, just add this to your manifest ( or at least manifest for debug). -
<application ...
android:allowBackup="false">
...
</application>
Read this:http://developer.android.com/guide/topics/data/backup.html
It's Important to mention here that process of backup is blackbox .. you don't know when it starts, and period between checks ... so better for developing to disable it.
is there a way to retain some of my data after uninstalling the app and than again installing it on the device. I need to check if my app had been installed on one's device previously or not.
Yeah it's possible if you save App Data in External Storage of your device because that data is not deleted even if your app is uninstalled.
Upon reinstalling the app, you can read the file data to determine was the app previously installed or it is a fresh install in case that file doesn't exists.
Note:- Data in External Directory would be visible to user so it might be a case that user may delete the data from file manager.
You can use shared preferences to store this data.
Create the sharedreferences with MODE_WORLD_READABLE.
You can set a flag as true when the app is run, and can extract this value on each installation to find out whether this value exists.
Something like below:
When the app is run(Write this code in the launch code for your app-which is triggered first):
SharedPreferences sharedpreferences = context.getSharedPreferences("test", Context.MODE_WORLD_READABLE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("app_already_installed", "true");
editor.commit();
Checking whether the app was already installed(Write this where you want to check for earlier installations):
SharedPreferences sharedpreferences = context.getSharedPreferences("test", Context.MODE_WORLD_READABLE);
String is_app_already_installed= sharedpreferences.getString("app_already_installed", "false");
if(is_app_already_installed.equals("true"){
//do-something
}
else{
//do-something
}
I will be releasing an update for my app with a new data structure, therefore if a user is updating my app I need to update their current data. So I was wondering how can I programatically check if the user updated my app or installed a new copy (if a new copy is installed I don't need to update anything) ?
SQLite
If your data is in an SQLite database, you can implement code in SQLiteOpenHelper.onUpgrade().
Checking previous version
If not, you need some kind of way to check the previous version that was open on the device. Something like:
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
// Use SharedPreferences to store something like "LAST_VERSION_RUN" = pInfo.versionName
Then, you can check if previous version is not equal to current version. Of course, this kind of code has to be in previous versions, also. There is no way to implement, once an app is already in the wild, a code that will detect whether an app has been upgraded.
Checking current version
I suppose what you could do in this case is detect the app version, and then set a flag to not update the data schema again. So, let's say your app version was 1.0.2, and is now 1.0.3:
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
if (pInfo.versionName.equals("1.0.3") && /* some SharedPreference value */ == false) {
// upgrade
// set SharedPreference value to true
}
I think that's going to be the best way to implement this if you're not using SQLite.
I have done an small App in Android, which I want to set as trial version for 2 days, after 2 days it should ask for a key. If the user uninstalls the App after expire date, he shouldn't be able to use the App without a key...
An idea could be release two versions of the app. One free version with some limitations or Ad's in it and another paid version of the app.
You need to setup a database which will be online assign a specific id to each device. If you are going to save the date of install in the SharedPreference or any local memory, the user can just remove it from his phone by simple clearing all the application data. He wouldn't have to uninstall it even.
So, every time a new user installs your application, you need to store the date of install corresponding to each device in your online database. Everytime the application is started, you need to ask the server for the date of install corresponding to that device and let the user proceed iff it is in the trial period, otherwise ask him for the key there.
I don't know, how safe/secure it would be, but you could use SharedPreferences to store this data. Just a really small example:
On startup:
SharedPreferences prefs = getSharedPreferences("AppName", Context.MODE_PRIVATE);
boolean firstRun = prefs.getBoolean("first_run", true);
long currentTime = System.currentTimeMillis();
if(firstRun)
{
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("first_run", false);
editor.putLong("first_run_time", currentTime);
editor.commit();
}
else
{
long firstRunTime = prefs.getLong("first_run_time", 0);
long twoDays = 2 * 24 * 60 * 60 * 60 * 1000;
if(currentTime - firstRunTime > twoDays)
{
//Expired
}
else
{
//Not yet expired
}
}
Please note, that if the user uninstalls the app, and then reinstalls it, or simply deletes the applications stored data, the "timer" will reset!
A safer method would be to store this data in an online database, but thats more complicated to solve, and it would require internet connection all the time to check if the app is expired.
Just use Android Licencing. It's pretty straight forward and awesome.
Anything more secure than that would be so much trouble. I don't think it's worth the effort for most apps.
http://developer.android.com/google/play/licensing/index.html