Save Data before Auto Update - android

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?

Related

How to know the origin of an event in Firestore?

Lets suppose:
I have an app installed in two devices, A and B.
This app listen to a person collection changes, as you can see:
FirebaseFirestore.getInstance().collection("people").addSnapshotListener((snapshots, e) -> {
if (e != null || snapshots == null) {
return;
}
for (DocumentChange dc : snapshots.getDocumentChanges()) {
if(dc == null){
continue;
}
switch (dc.getType()) {
case ADDED:
onDocumentAdded(dc.getDocument());
break;
case MODIFIED:
onDocumentModified(dc.getDocument());
break;
case REMOVED:
onDocumentRemoved(dc.getDocument());
break;
}
}
});
When device A adds a new person to the people collection, device B will be notified about it, but device A as well.
In my case, I am implementing Firestore in a existing app and it already have a persistence logic.
In fact, whenever a new person is added by device A, I already have it stored in the app of device A, but I want to save it in device B as well.
However, as device A is notified too and I would save this person twice.
Some solutions I've been thinking:
Storing an unique ID (UUID) on my local database and check if exists (but on Modified event it would not work);
Defining a client ID (UUID) and send it. When I get the notification by the listener, I check if the client ID is the same I have defined locally.
I asking it because I do not know if already exists a way to handle with it.
If device A creates the document, and you have an active listener on the document created (or in this case, it's collection), you should find that snapshots.getMetadata().isFromCache() == true and the document added should also have a similar trait - dc.getDocument().getMetadata().isFromCache() == true.
However, this is not entirely fool-proof, as documents that have Field Transforms such as serverTimestamp() may only fire the listener once they been accepted and resolved by Firestore.
An alternative is to simply add the new person to Firestore (without saving it locally first) and let the snapshot listeners handle persisting the data. As mentioned above, the listener will normally be fired locally while the data is being sent off to your actual Firestore database.
Whenever I needed this, I've kept a list of the document IDs that the local client has written in local storage, and then check the snapshots in the listener against that list.
It's a bit of a brute force approach, but pretty simple to implement. And if you prune the IDs from the local list in the listener once you've gotten the update, the memory overhead is pretty minimal.

How to remove User data from my app through Ionic?

I have an Ionic 4 App that use IonicStorage with IndexDb .
The user will take some photos that will be saved in the storage. After the process is done, if the user will take a look into app settings will see something like this:
Problem:
When the user will attempt to perform another login the user data must be erased, cleared. I tried to delete the data by calling the clear method from the storage.
/**
* Clear the entire key value store. WARNING: HOT!
* #returns {Promise} Returns a promise that resolves when the store is cleared
*/
public ClearStorage(): Promise<any> {
return this.ionicStorage.clear();
}
Also I added these flags in the config.xml ...but without success. I can't erase it
...
<application android:allowBackup="false" />
<application android:fullBackupContent="false" />
...
Can you suggest me something. Ty
I understand whats happens with the storage and with the user's data. The problem is not the clear function, it's working perfectly fine. The problem is that the methods from the storage object are logged into a specific file. Basically when I save a base-64 photo into a storage object it automatically add a new entry to the log file (eg: One base64 string image has around 500kb so the log file size will increase with 500kb).
The file is also private. The problem that also remains, so how can I delete the log file from Ionic?
Try this.ionicStorage.remove('yourStorageKey') for each of your storage keys to remove all data in IndexedDB or sqlLite.
Yes, this is working just on the app storage (saw it through chrome inspector). The user data are not cleared.

Android SharedPreference do not working

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

When to use getSharedPreferences vs savedInstanceState?

I'm trying to figure out when to use a saved instance state versus loading information from a shared preferences file. I have two variables that I wish to save, time and score. I want to make sure that if the user returns to the game screen that their score and time is saved and restored regardless if it's from onPause state or onStop.
I have three keys:
public static final String ARG_SCORE = "score";
public static final String ARG_TIME = "time";
public static final String SHARED_PREFS = "shared_preferences";
If the game is paused and a dialog is shown, when the user returns should I do
public void onRestoreInstanceState(Bundle savedInstanceState){
int score = savedInstanceState.getInt(ARG_SCORE);
}
or should I do something like:
protected void onResume(){
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int score = sharedPref.getInt(getString(R.string.saved_high_score));
}
Overall, I need help understanding the lifecycle and when to store vital information such as time and score of the game. I simply need to avoid the user having to restart in cases they weren't able to finish the game.
Lastly, I'm assumed that the sharedPrefs saves to an xml file. Is this correct? Does anyone have a sample xml for how my sharedPrefs should appear? Do keys which are saved to bundles of savedInstanceState get stored in xml files as well? If so, any examples? If not, where is the information stored?
THANKS!
edits:
ok cool beans. Thanks! One more question, when defining a key for a key-value pair stored into sharedPreferences such as
public static final String ARG_SCORE = "score";
why is the "score" string stored? When would this ever be used? I've always placed a value into the key_value pair using something like
args.putInt(ARG_TIMER, timerINT);
and retrieved using
scoreINT=savedInstanceState.getInt(ARG_SCORE);
Why is a name needed for the key ARG_SCORE? When would I need the name? Does it have to stay type String?
use saveInstanceState when you are frequently moving back and forth between activities and use SharedPreferences when you want to keep information for long time and yes sharedpreferences stored in an xml file. you can view using DDMS in eclipse.
Remeber, in saveInstanceState, when you close app mean it get removes from memory, information will also lost. And in SharedPreferences, information will remain there if you close your app.
It will depend on how you want to manage the data. Both options (and more) are feasible:
If you want to fill once and keep the data even if the app gets
killed, use SharedPreferences.
If it's volatile data that will have to be reentered differently some
other time (i.e., days later), then use onSavedInstanceState.
If you want to keep multiple datasets on the same device, then use a
SQLiteDatabase
You usually want to use SharedPreferences when you want to persist some information between different app session. Imagine you want to store information that you want to retrieve also after the user closes the app.
SavedInstanceState is used to keep some information while user is using the app and allow you to track temporary state of your activity or fragments.
Hope it helps.
when you press home button then still your activity remains in background. since there is some memory constraints in android , there is always chance some other application can take your memory. so to resume application from same point where we have left we use saveInstanceState.
we use sharedprefrence when we have to save small info(normally primitive type) like game high score in any game.
In the Android documentation says how to relate SharedPreferences to XML but there's no need to use SharedPreferences if you don't want the data to be stored forever, you can store the game's state using the Activitys lifecycle methods with no problem, but for example, if the user turns off it's phone or presses the back button to finish your Activity, then the savedInstanceState won't work and you will lose your data.
It's your call, if you want the game to be saved even if the user turns off his phone (I think this would be kinda radical, but if it's your requirement go ahead) then use SharedPreferences or a DB if it's complex data. If you want the game to be saved only when the user navigates in and out to your app, then it's safe to use the savedInstanceState.

How do I know which app version is being replaced with android?

I have an update that I want to run for my app based on what the previous version of the app is.
For example, if the user has version 1-5 and they are upgrading to 6 or 7 I want to run the update. Also, I don't want to run the update if they are upgrading from 6 to 7.
I've tried to accomplish this using a broadcast receiver that accepts the PACKAGE_REMOVE and PACKAGE_REPLACE intents but they don't seem to give me the information about the app that is being removed. I don't get the PACKAGE_REMOVED intent unless I'm reinstalling the same version. It's hard to tell because the debugger and the log print don't seem to catch before the intents are received. Any ideas?
#Override
public void onReceive(Context context, Intent intent) {
if (isOccurUpdated) {
return;
}
if (action.equalsIgnoreCase("android.intent.action.PACKAGE_REPLACED")) {
String name = info.versionName;
// We are assuming that we didn't get down here if we have already
// done this update
Log.d(TAG,"We receive the REPLACE intent "+name);
if (name.contains(OCCUR_ID_UPDATE) || name.contains(OCCUR_ID_UPDATE_FIX)) {
dbh.occurIdUpdate();
}
} else if (action.equalsIgnoreCase("android.intent.action.PACKAGE_REMOVED")) {
String name = info.versionName;
if (name.contains(OCCUR_ID_UPDATE)) {
isOccurUpdated = true;
}
}
}
You need to store previous-version information yourself somewhere, such as:
Step #1: Create a custom Application class, and define it in your manifest (android:name attribute of <application>).
Step #2: In onCreate() of your custom Application class, read in some persistent data structure that contains the version number of your app the last time onCreate() ran. For example, you could have a lastVersion value in your SharedPreferences.
Step #3: If you see that the last version is older than your current version, do whatever upgrade logic you want.
Step #4: Write your current version out to that persistent data structure (e.g., update the SharedPreferences).
If this is more tied to database logic, SQLiteOpenHelper handles all of this for you.

Categories

Resources