Value of Application Context Variables Lost on Application Error - android

I noticed that when my application encounters an error, the value of my application context variables are also reinitialized to its original value (not the updated value). Based from my understanding, this happened because the application was recreated.
How can I save and restore the values of my application context variables when an application error occurs? I'll also be glad if you could give a more detailed explanation on how things are working on the background of my application when it encounters an error.
Note: I read that one of the solution for this is by using SharedPreferences. However, SharedPreferences saves the data even when the application is dead. I don't want to save the data when the application is dead. I only want to save the data when the application is alive or on background.

How can I save and restore the values of my application context variables when an application error occurs?
First, don't have an unhandled exception.
Second, don't rely on static data members or custom Application subclass instances. There are many scenarios in which your process will be terminated and those values go away. They should be used for an in-memory cache of persistent content, and little else.
Sometimes, unhandled exceptions are truly unexpected, but these should be infrequent and usually tied to specific devices (e.g., ran out of storage space). Everything else represents a bug in your app, and you must fix the bugs.

Related

How does android do GC?

Now I'm facing some problem in Android when memory is low or the application is killed by system.
Scenario 1:
I set some static members in a class, I found in some situation , it will be deleted by system when the application is still running.
My problem to this is : when does this kind of GC run?
Scenario 2:
If I switch to another large application and then switch back to my application ( named App_A). App_A sometimes will be recycled by system and restart the last activity when it be switched back.
But there are some application-wide data (like login info) I saved in a singleton.
My problem to this is : Dose the application-wide data saved in singleton will be deleted?
If so, is there a appropriate way to restore the data?
My effort is:
To Scenario 1, I will avoid to use static member directly.
To Scenario 2, I will save those data into file , after it be deleted, I pass Context to each public function to let each of them have the ability to restore the data. But I think it will be unfriendly when the function is used in some situation which need run quickly.
I can only answer about Scenario 2.
Android will try to keep recently used apps in memory, but if the user switches to another app and memory starts running low, the OS has the option to kill the recently used app to make more memory available to running applications.
I had the same problem, where I had some user-context data like username in a static singleton. This data would disappear when returning to the app after using a number of other apps.
The way I solved this problem was to use the activity's intent. Since the user data was retrieved at the beginning of the app, I would simply pass this data to subsequent activities in their intents. Because the OS stores the intent and uses it to recreate an activity not in memory, my data was no longer vulnerable to being garbage-collected.
Also consider other means of persisting data: Shared Preferences, file system, SQLite database. But never count on static data from previous execution being available at the start of an activity.
It is generally bad idea to use singleton to save some data.
Best practice is using any persistent storage - SQLite, Realm,JSON, or any file.
Easiest way is saving your login data for ex. in JSON - then in Application class parse it in onCreate method into POJO - then you can get it from any place of your app. And store to file when app is closing or on any change.
Anyway I suggest you to read Android guides about persistence, memory management and performance tips.

Android Static ArrayList

I am building an Android application and I am using a static arraylist which I populate during the Splash Activity so that I can use it throughout my whole application. But when I am exiting and re-enter the application, this array remains full with its previous contents. What is happening please?
If it's static it will only be deleted if the class that holds it is completely unloaded from memory. That probably won't happen immediately, but will at some point in the future. You should manually clear it when you know you don't need it anymore. Or store the data somewhere else.
If you were to really kill your process via ADB (not just by exiting your activities), you will notice that the data will be gone.
Without more details it's hard to say for sure but my guess is you may have a reference to your context somewhere so you application is never being closed hence when you rerun it you're seeing the same data there as it's using the same object.
You can probably confirm this by going into the running processes part on the phone or via the adb to see the process still there.
The usual reason is having a drawable and not cleared it's callbacks before exiting which keep a reference to the context which will therefore keep a link to your Application. If your static variable is declared in your activity it will mean it remains there.

Data on a Extended Application class lost when app is closed

I´ve an Android Application that holds some static objects on an class that extends Application class, using the same approach as exemplified here.
The objects that is hold by this class is shared and manipulated between all activities on my app.
Everything works well, but, some time ago, I noticed that when the application runs on backgroud for some time, when it´s restored, the data that was stored on the extended class has gone, and the app starts to throws a lot of NullReference exceptions.
I think that this happens because of the application was being temporary destroyed by the OS, to be recreated when we need to use it again.
So, how could I handle this scenario? Is there any way to discover that the application is being temporary destroyed, without subscribing to the onDestroy event of an Activity? On a test that I did, the onDestroy event was not called when I asked the background process of my app to being stopped.
Thanks a lot!
There is no way to determine when the proccess will be killed, so you always should store important data somewhere(sd-card for example) and restore it in onCreate() method of your App class.
Also take a look at onLowMemory() and onTrimMemory(), release all unnecesary data in memory to help the OS prevent destroying your app, cause one of the reason to determinate your app is a lack of memory.
No, there's no way to tell when you need to persist data that you store in static variables like that. There's no callback that the systems notifies you about this, at least to my knowledge.
So you should only use static variables to store temporary data, or cache data accessed from peristent sources. I've faced this problem in many of my projects, and I always ended up using intents / shared prefs / sqlite / etc. to reliable store data across Activities.

Where is the bundle of onSaveInstanceState saved?

I would like to know where the bundle "outState" of the method onSaveInstanceState(Bundle outState) is stored.
Is it stored in memory or in the device storage?
I am concerned about the security of the data which is stored in the bundle.
To store data only for application lifetime (ie temporarily), use the onSaveInstanceState(Bundle) activity event
This data will only be held in memory until the application is closed, the data will be available any time that this activity starts within the current lifetime of the application.
Explanation: if data is stored here by activity A then the application shows a different activity or rotates the screen (hence closing A) and then returns to A the data can be retrieved to populate the controls. However if the application is closed and opened again the data will be gone and the controls will revert to their default values.
Example of use: storing text typed in by user and selections making up an order, blog entry, message, etc...
Note:
It’s important to notice that only the Activity is destroyed and recreated, not your whole application! An Android application can consist of many Activities, Services and ContentProviders! If the application is closed (for example by pressing the “Back” Button, then all values will be gone. savedInstaceState is only there to preserve data temporary when an Activity is destroyed/recreated, not the application itself.
If you want to preserve data permanently, you need to save it either as Preferences or in a ContentProvider/database.
Here is a detailed answer for where the outState Bundle data is saved:
...Bundles are an IPC mechanism, so it's not going to the filesystem. But now there's a P involved – which process is it? And what is that process doing with this data? And do I need to be worried about it? It turns out that these instance state bundles are stored in the Activity Manager service. This service is implemented under the package com.android.server.am in the Android source code. Recall that Activities are stacked one on top of another and that Android calls these stacks “Tasks”... Each of these tasks is represented internally with an object of class TaskRecord. This class contains an array of ActivityRecord objects, each of which manages the state of an Activity. ActivityRecord contains a member of type Bundle named icicle. This icicle-bundle is the saved instance state and it is actually stored in the memory space of the Activity Manager service.
Source: https://www.linkedin.com/pulse/android-onsaveinstancestate-bundle-secret-safe-daniel-pietsch/
The documentation has been updated and indicates precisely that the state is serialized to disk:
Saved instance state bundles persist both configuration changes and process death, but are limited by amount of storage and speed because onSavedInstanceState() serializes data to disk.
You can also found a table comparing the differents approches to preserving UI state
Source: https://developer.android.com/topic/libraries/architecture/saving-states
I don't think there's any way that any malicious background process can get at the bundle data of your application. It is not documented how Android treats the Bundle data. It may or may not be written to disk in the event that your app is cleaned, while backgrounded. However, given that we don't know whether or not this data is saved to disk, and if it is, given that we have no clue where, and almost certainly don't have read access to that part of the disk, I wouldn't worry about some third party process being able to recover that data.
Consequently I'm not clear what you might think the exposure is. Though I may be missing something.
However, in answer to your question, it is absolutely in memory while your app is alive, and if your app is backgrounded it may or may not be written somewhere hidden, but we dont' know because Google hasn't told us.
It's destroyed along with the application when the memory is collected.
My guess would be in memory, but the best way to protect your data would be not to trust the system and encrypt it. Never trust the client (in this case the client being the OS).
EDIT:
To be clear, I'm not saying encrypt the bundle. Rather I'm saying that any sensitive data should not be put into the bundle. If you must put custom data in the bundle, then encrypt it.
But ultimately you should keep as little sensitive data on the client as possible. This is the same reason a e-commerce site would only show the last 4 digits of a credit card.

Frustrating but quite common taking SNAPSHOT problem!

Taking photos using system provided component(MediaStore.ACTION_IMAGE_CAPTURE) is quit common.
As Ive experimented, with a certain rate the android system will kill the snapshot calling Activity to prevent memory related exception, and the calling activity will be created again where returned. Thus I have to save the states of the calling Activity via onSaveInstanceState, and retrieve them via onRestoreInstanceState. (If Im not correct and there is further info, please point it out)
However, I also found out that, when the killing occurs, all my information stored in the RAM were ERASED, RESETED, for example those Singleton class type objects, or static classes and their fields!
This mechanism is so frustrating, how to handle such situation??
I`ve found it out...
Some android OS kill the snapshot calling Activity to avoid memory related exception. So, I have to save all the states via method onSaveInstanceState, and retrieve them when the calling activity was constructed again.
Further more, I also found out that, all the information stored in the memory is prone to be erased, like those Singleton objects. Thus I have to do saving by some persistent storage approaches, and restore them later.

Categories

Resources