Android Bundle = .NET Session[]? - android

The description of Android Bundle says:
Bundles are Android's way of maintaining and passing program state. The system is constructed around the assumption that any program (characterized by a collection of activities) may be preempted at any time, and if the system resources are low, may be subsequently killed. To handle this difficulty, a Bundle called an icicle is saved whenever the activity is preempted.
Like with a hash table or dictionary, items added to the Bundle are given a key which is later used to retrieve the data (using data-type specific methods like getCharacter(String key) and getParcelable(String key)). When you are creating activities, be sure to save any important state information into the icicle given to onFreeze so that you can restore your program in onCreate if it is killed while suspended.
Is Bundle the same as Session[] in .NET?

Not exactly, no.
In .NET the you can access the State object from anywhere at any time, and you will be pretty sure that objects that you have placed inside of it will still be there when you are calling it. The session expires though, and unless you have saved anything in your viewstate, that data becomes lost.
Android uses Bundles because of the nature of the OS, it will keep your application "alive" in the background where state is preserved, but if it deems that your application is idle and that it can be killed, it will kill your app to free up resources. Before your app process is killed it will call onFreeze() (now renamed to onSaveInstanceState()) which will give you the opportunity to save data to the Bundle that will be passed to onCreate the next time your application starts up (so you can initialize your screen again).

Related

How long does a Bundle last?

I know that a Bundle can be used to pass data between activities, as well as for saving and restoring data in cases of configuration changes like a screen rotation.
I also read that SharedPreferences is the preferred way to store persistent data, rather than a Bundle.
Why exactly is this the case? In order for a Bundle to handle a configuration change, it would have to persist even after an activity is destroyed. So what exactly is the lifespan of a Bundle? Is there a certain point where it arbitrarily gets eliminated by garbage collection, or does a Bundle's data persist for as long as you don't manually choose to clear it?
Bundle lasts while the Activity exists, aka it has not been finished.
An interesting fact to note is that when process death occurs and Android massacres your application and the Application class is recreated (onCreate() is called), then the Activity stack is reconstructed, and the activity is reinitialized from the saveInstanceState bundle.
The SharedPreferences literally stores the data you give it in an XML file in the data/<applicationname>/preferences folder, if I remember the location right.
SharedPreferences are for simple persistent settings storage. Like the home page on a Browser that should be available every time the user opens the app. These are just key:value pairs designed to hold simple things.
Bundle is a way of storing data to either pass to another Context (another Activity, Service, etc) or to save and restore your own current state in onSaveInstanceState and onRestoreInstance state. This data is NOT persistent and used while the application is in use.

Android onSaveInstanceState Bundle

When android kills your process due to system constraints it gives you the ability to persist data across processes by storing the data in a bundle. Where is this bundle saved if your process is killed? Which process does it live in? Where in memory does it live in? Does it live in kernel memory?
Kernel memory is a protected memory space where only critical code like the kernel code reside. This is to prevent interference of data from the user and that of the kernel and also for other performance and design reasons. Kernel memory will persist through a reboot.
The data being persisted in the Bundle is passed in the method of the onSaveInstanceState() - before the user leaves the Activity not before the Activity gets destroyed. This likely means that the memory is not written in a static memory area like the memory card. The Bundle will indeed be persisted but in a more dynamic way.
While this question has not been directly answered, it looks like this is memory on the RAM. When you look at the performance of Android devices, the more recent devices with more RAM seem to be capable of holding on to apps for much longer
From the official documentation at http://developer.android.com/training/basics/activity-lifecycle/recreating.html, it is understood that this memory is tracked by Android itself.
By default, the system uses the Bundle instance state to save
information about each View object in your activity layout (such as
the text value entered into an EditText object). So, if your activity
instance is destroyed and recreated, the state of the layout is
restored to its previous state with no code required by you. However,
your activity might have more state information that you'd like to
restore, such as member variables that track the user's progress in
the activity.
To save additional data about the activity state, you must override
the onSaveInstanceState() callback method. The system calls this
method when the user is leaving your activity and passes it the Bundle
object that will be saved in the event that your activity is destroyed
unexpectedly. If the system must recreate the activity instance later,
it passes the same Bundle object to both the onRestoreInstanceState()
and onCreate() methods.
Also keep in mind that this Bundle gets destroyed when the device shuts down. Android might have a specially designed memory area for this but either way it is somewhere in the RAM.

Activity Recreation on Android

I am reading the official Android tutorial on Managing Activity Lifecycle. Please have a look at the following points as I quote.
(Normal app behavior)
"When your activity is destroyed because the user presses Back or the activity finishes itself, the system's concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed."
(System induced destruction)
"If the system destroys the activity due to system constraints (rather than normal app behavior), then althought the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed."
"The saved data that the system uses to restore the previous state is a collection of key value pairs stored in a Bundle object. By default the saved information is about the activity's view hierarchy, such as the text entered in a widget, the scroll position, etc. To save additional state information for your activity, such as member variables, you must implement onSaveInstanceState() and add key-value pairs to the Bundle object."
Please see if I can sum up correctly from the above:
The system is resource conscious and can destroy an activity to recover memory. If the system does that then it leaves an option of recovering the destroyed activity to its previous state if needed later.
State = view-state (default, done automatic) + member-variable-state (manual, up to the programmer).
My question is, if the system is destroying an activity in order to free some memory, then doesn't it defeat the purpose if it allows us to keep a "copy" of the activity so that the activity can be restored
to the point exactly as it was prior to destruction?
No, it does not defeat the purpose:
A Bundle is optimized for being serializable, so the Android framework could just write it to disk.
The data you need to represent your state is much smaller than the amount of RAM you need for a running copy of your app. For example, if you show an image to the user, you'd probably just have to save the image's location, not all of its data. Also, every Android app is a whole new Dalvik VM, so if all the activities are from different applications, killing an activity means one Dalvik VM less – and every Dalvik VM probably needs a relatively big amount of RAM.

Are the bundles in android permanent in saving activity states ?

When I want to save some state behavior of the activity, The docs says that we should implement OnSaveInstanceState and OnReceiveInstanceState.
They say that this will save the activity state even after destroy or restarts. I care more about destroy (the activity is completely gone) , does that mean the bundles are considered persistent ?
when I open a pdf reader, clost it and open it again i see that it opens in the same page I was in. is this implemented using Bundles or oth
To store persistent application data use Shared Preferences. Shared Preferences are simply sets of data values that are stored persistently. By persistence, we are talking about data that persists across application lifecycle events. In other words, the application (or device, for that matter) can be started and stopped without losing the data. The next time the user launches the application, that data will still be available.
Some Games use Shared preference for exemple to store the level of the game reached, the player's name ...
see this link to learn how to use Android Preference API
Preference are simular to bundles However they are persistant and bundle are not!!
Keep in mind that if you need to store persistent data you have 4 options to do this:
Using Shared Preferences
Using SQLite Databases
Using Internal Storage
Using External Storage
Bundles are not persistent, the documentation says not to count on it, onSaveInstanceState() is called when the activity is about to be killed by the system, but for a known restart (for
instance on a screen rotation.) If your activity is killed because the system needs more resources (while the
activity is in the background), onSaveInstanceState() will not be called, but onPause() will. onSaveInstanceState()
really is not meant to save persistent data, as the doc states.
You can sorta consider SavedInstanceState() permanent but it's not recommended to use it for saving application related data in a persistent manner as It's not guaranteed to be called and it's not recommended by the authors themselves.
so, Only use them for saving user interface state changes (background color, currently selected items ,..) and use other method for persistence like : SharedPreferences, Files and SQLite.
Bundles are not persistent, and the documentation for them specifies that using them for persistence is not a good idea as their internal format may change between devices or even OS versions.
SharedPreferences, on the other hand, can be persisted and are the recommended way to store information like current app state.
Some relevant parts from SavingActivityState
:
Note: There's no guarantee that onSaveInstanceState() will be called before your activity is destroyed, because there are cases in which it won't be necessary to save the state (such as when the user leaves your activity using the Back button, because the user is explicitly closing the activity).
There is no guarantee data will be stored, especially in the case where your user exits the app.
Note: Because onSaveInstanceState() is not guaranteed to be called, you should use it only to record the transient state of the activity (the state of the UI)—you should never use it to store persistent data. Instead, you should use onPause() to store persistent data (such as data that should be saved to a database) when the user leaves the activity.
So like K-ballo said, used SharedPreferences if you have persistent data to store. onSavedInstanceState() is mostly useful for storing UI related data.
As every one else has recommended use shared preference and you should do this saving in onDestroy and onSavedInstance both.
When android is going to run low on memory, its just going to kill your application and call your onSavedInstance without calling onDestroy etc. Save your context in bundle it passes in onSavedInstance. When your app comes in foreground again, android will take care of restoring your back stack of activities. But this time it will pass you the bundle in your onCreate for each activity which will have all the values you saved in your onSavedInstance while your app was getting killed.
Hope this helps.
Short answer: It's not permanent.
Long answer: From "Android Programming - The Big Nerd Ranch Guide":
When onSaveInstanceState(...) is called, the data is saved to the
Bundle object. That Bundle object is then stuffed into your activity’s
activity record by the OS
...
So when does the activity record get snuffed? When the user presses
the Back button, your activity really gets destroyed, once and for
all. At that point, your activity record is discarded. Activity
records are also typically discarded on reboot and may also be
discarded if they are not used for a long time.

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.

Categories

Resources