Variables being garbage collected - android

I have an android application that is running. After a while when user quits the application by running something else, and returning to my app, the static variables in the application is seem to have been garbage collected.
In a nut shell, I'm keeping the entered username/password at startup of the application and keep them in a static variable, and use them for communication with server. I either need to find out when they are garbage collected at application re-launch (so that I redirect them to login view) or prevent this class from being garbage collected. Ideas?

One way you could implement your second scenario is by implementing your own class that inherits Application, and specify it in your manifest. You can put your static variables in that class. Android will create one instance of that class when it launches your process, and that instance will be alive as long as the process is alive too.
So, if you have a simple boolean in that class that denotes if a signin has been performed, you now have a reliable way to check at any point whether you should direct the user to the login activity, or try using the in-memory username/password.
In addition, you could use one of the standard Android persistence component (shared preference file, SQLLite, AccountManager, OBB, credential storage, etc) to persist the credentials across process restart. Note however, that doing so raises a whole new set of issues around how to properly secure that persisted copy of the user credentials, in order to protect it from unauthorized access by other applications (especially on rooted phones).

I suggest not trying to "prevent this class from being garbage collected". Instead, work within the framework as it was intended.
(Not addressing the topic of user authentication or credentials management...)
Android provides a few options for storing data, outlined at http://developer.android.com/guide/topics/data/data-storage.html. For your situation, using preferences might be a decent, light-weight, easy-to-implement option.
Also, note that keeping the values in an Activity's members might well-solve the problem, if the app has an Activity that's using the values. If so, then note that use of onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle) may be in order.

Related

Avoid crash with multiprocess and Application onCreate

From Firebase docs they say:
Multiple processes
Crash Reporting creates a separate background process to upload crash
info. If your app extends the Android Application class, you must
ensure it is multi-process safe. Otherwise, it may cause concurrency
issues. When an app extends an Application object, this object gets
instantiated for each process in a multi-process app. Two important
things to watch for are:
If the implementation of this object accesses any out-of-process state
(a database, the file system, shared preferences, etc), or performs
other actions not safe for a multi-process environment, concurrency
issues might arise. This is because multiple instances of the
Application object may run simultaneously. Many third-party libraries
keep out-of-process state (e.g. in a local database) and are subject
to the same concurrency issues if they are initialized from the
Application object. If your app fits the description above and you
plan to use Crash Reporting in your app, we strongly encourage you to
consider moving the Application logic to Content Providers, or to
Android Activities. Any Application logic that is not safe for a
multi-process environment can have unintended effects on your app.
How can I check from my Application class if theres another instance inside the Application onCreate to avoid crashes with Fabric or others?
Generally speaking, you don't "check to see" if there is another Application object from another process. You simply assume that there is always exactly one Application object created for every process in your app, and ensure for yourself that it will be safe to run in conjunction with other Applications objects in other processes. Just don't access any shared read/write resources from Application and you will be fine.
If you must initialize something from only the main process, a more reliable way of doing this is to create a ContentProvider (declare in your manifest and create an object for it like any other component), and use its onCreate(). ContentProviders are only created and initialized from the main process - never from other processes. This way you can be sure that your init will not be duplicated in any other process.
Or if you don't want to deal with this at all, just wait until Crash Reporting comes out of beta to full release, as it will not use an extra process at that time in the future. We (Google) can't say exactly when that will be, but we're not wasting any time in getting the full release published.

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.

Persisting state in the android Application class

I am developing an Android application consisting of over 10 activities. I have some state objects that I access in almost every activity and for this purpose these were implemented as global static variables in the MyApplication class.
I noticed that this approach is OK as long as the user is "in" the application. However, when he presses the home button and opens another apps and then goes back to my app through the "Recent activities" button, I see that the Android system resets the statics from the MyApplication so I have to deal with NullPointerExceptions. I know that this behaviour is caused by Android killing and recreating the application process.
I know that the best way to persist this kind of data is using SharedPreferences or SQLite, and I have no problem checking if MyState==null in the onCreate for and restoring it, but the problem is that I don't know when to properly store my state object (in prefs or database). I tried to override MyApplication's finalize() - no good, I saw that onLowMemory may not be called, I don't see how can I use onPause, OnStop and so on because I have so many activities that the serialization de-serialization would considerably slow down the app.
Any thoughts?
Thanks in advance!
It is better to not depend on the Application class unless you need to load some data, before anything else is started. Android can kill your process at any time to free resources, so your app should be able to handle this. Save all of your data in a snigleton class, and load it lazily -- check for null, and if so load on first access. It the state needs to be persistent, consider staving it file/shared prefs. If not, your app can probably live without it, so just make sure you check for null, etc.
Generally, you should persist state when activities become inactive -- onStop(), onPause(), but you can save as soon as it makes sense (e.g., the user has entered all required data). Spin off an AsyncTask to save data in the background and let the user continue their work.

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.

ANDROID - class Application

I'm trying to understand how the Application class.
I've noticed that need to declare it in <application> manifest within the tag and then can access the variables in other classes as they were global variables. And even out of the application the value of these varieties do not change.
However, if you unplug the phone, the next time you turn it on and start applying the value of the variables returned to its initial state.
I wonder if you can maintain the state of variables when we turned off the phone and reconnect it?
Application data is available as long as your application is "active". When the OS decides to terminate it to clear memory, so goes your application data (you typically don't control when this happens, as per the mobile development good practices: the OS decides on its own), and it's not persisted for the next time you start the app. So anything you store in the Application should be stored again each time the app is started.
It should be used to keep short-term data available to you. A good use case is when you need to access a complex data structure from multiple activities: it's not possible to use bundles for that. You can generate your complex data structure in your start activity, store it in the application, and then retrieve it in any other application that may need it.
But you should not use it for long-term persistent data. For that, the best is to use a SQLite database.
I'm not sure I fully understand what you mean, but it seems like you want to use Shared Preferences.
try this Question: Android - How Do I Set A Preference In Code

Categories

Resources