# Warm up: Recall our [Hope/Expectation](https://edstem.org/us/courses/38124/lessons/59392/slides/331337) from the first day of class. Now fill out this [survey](https://edstem.org/us/courses/38124/lessons/59408/slides/331437)... --- name: inverse layout: true class: center, middle, inverse --- # Storage Lauren Bricker CSE 340 Spring 23 --- layout: false [//]: # (Outline Slide) # Today's goals - Administrivia - Layout part 3-4 & reflection due Thur 20-Apr - Practice quiz 3 out, due Sunday 10pm - **Finish [Properties of People - Vision](people-vision.html#34)** - Storage - Bundles - Shared Preferences - [Android Security](security.html) --- [//]: # (Outline Slide) # Today's goals - Administrivia - Layout part 3-4 & reflection due Thur 20-Apr - Practice quiz 3 out, due Sunday 10pm - Finish [Properties of People - Vision](people-vision.html#34) - **Storage** - Bundles - Shared Preferences - [Android Security](security.html) --- # So you got lots of apps.. -- .left-column50[ ![:img Android Activity Lifecycle which shows when the operating system starts; pauses and kills android processes, 80%, width](img/storage/activity_lifecycle.png) ] -- count: false .right-column50[ They all want to use _tons_ of memory... ] -- count: false .right-column50[ ...but they don't **need** that memory all the time. ] --- # So you got lots of apps.. .left-column50[ ![:img Android Activity Lifecycle which shows when the operating system starts; pauses and kills android processes, 80%, width](img/storage/activity_lifecycle.png) ] .right-column50[ What happens when the user closes an application? Does it completely go away? ] -- count: false .right-column50[ It depends... ] -- count: false .right-column50[ ...was it completely unloaded or did it essentially hibernate? ] -- count: false .right-column50[ However.... ] --- # So you got lots of apps.. .left-column50[ ![:img Android Activity Lifecycle which shows when the operating system starts; pauses and kills android processes, 80%, width](img/storage/activity_lifecycle.png) ] .right-column50[ **Android**: You get no/minimal memory when you're not actively being used. ] -- count: false .right-column50[ **Apps**: But wait! You took away my memory, all my variables are _GONE_ 😲. How do I remember things when I *am* being used if you take away my memory? ] -- count: false .right-column50[ **Android**: Store it! ] --- # Storage options There are two main types different storage options to save data - - Short term volatile memory - Data that goes away when the phone is turned off - Long term memory - Data that can be recovered when the phone is turned off and back on --- # Short Term Storage option [Bundle](https://developer.android.com/reference/android/os/Bundle) - Usually stores a small amount of data - Saved RIGHT before the memory is cleared. - Typically used when you want to safely transfer data between activities or between an activity and a fragment. - The `Bundle` is sent back when the activity starts running again. - A `Bundle` is destroyed if the user **force quits** the app/phone is turned off. .footnote[More on [Activity state and ejection from memory](https://developer.android.com/guide/components/activities/activity-lifecycle#asem)] --- # What is in the Bundle? You, the application developer, decides what needs to be stored Values are mapped to unique KEYS (for set/retrieve) The `Bundle` is like a `Map
` that only supports `Serializable` objects (like primitives and `String`) --- # Bundles: Code Example ```java public abstract class MainActivity extends AppCompatActivity { @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("OUR_KEY", "bundles? bundles!!!"); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); String whatWeSaved = savedInstanceState.getString("OUR_KEY"); // whatWeSaved would contain "bundles? bundles!!!" } } ``` --- # Modifying Doodle To save which Tab/Activity shown in `Doodle` we could modify `AbstractMainActivity.java` to store it in a `Bundle` ```java protected static final String CURRENT_TAB_ID_KEY = "ACTIVITY_TAB_ID"; private TabView mNav = findViewById(R.id.bottom_nav); protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // Get the current tab id, and store it with CURRENT_TAB_ID_KEY outState.putInt(CURRENT_TAB_ID_KEY, getTabId()); } protected void onRestoreInstanceState(Bundle outState) { // get the tab from the bundle at CURRENT_TAB_ID_KEY, defaulting to // R.id.action_part_1 & set the nav accordinly! int current = outState.getInt(CURRENT_TAB_ID_KEY, R.id.action_part_1); mNav.setSelectedItemId(current); } ``` We will see this more in Accessibility --- # Bundles & Code - Bundle management is occuring at the `Activity` layer, not to be confused with any individual `View`. - When the user closes the app, right before it closes and its memory is cleared, Android invokes `onSaveInstanceState(Bundle outState)` on the activity, providing a reference to the activity for the app to save values into. - When the user opens the app again, Android invokes `onRestoreInstanceState(Bundle savedInstanceState)` returning the same bundle from earlier. _(Read more [here](https://developer.android.com/topic/libraries/architecture/saving-states))_ --- # Bundles & Code - Bundle data is transient - it will go away if the app is completely unloaded from memory. - Typically small amounts of data (< 1MB data total) - Used to share information between activities. --- # How can we store things for longer??!?!? --- # Long Term Storage Longer term, persistent storage stay around even if the phone is turned off. Shared Preferences - Store private primitive data in key-value pairs. Internal Storage - Store private data on the device memory. External Storage - Store public data on the shared external storage. SQLite Databases - Store structured data in a private database. Network Connection - Store data on the web with your own network server. .footnote[From [Android documentation](https://android-doc.github.io/guide/topics/data/data-storage.html)] --- # Long Term Storage Note that the app *could* write/read its state to longer term storage whenever it is being closed/opened ... -- ... but that is time consuming and would delay the OS launching new things... --- # Shared Preferences Stores data in persistent internal memory on the phone. Like `Bundle`, also stored in Key Value pairs [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) documentation --- # Shared Preferences To see what is in your shared preferences 1. start the Device File Explorer (View->Tool windows->Device File Explorer) 2. Use the toggles to open up the following folders ```` data data
for your app, such as cse340.askforhelp shared_prefs
.PREFERENCES.xml ``` --- # Shared Preferences Creating the Shared Preferences File ```java protected SharedPreferences getPrefs() { if ( mSharedPreferences == null ) { try { Context context = getApplicationContext(); mSharedPreferences = context.getSharedPreferences(context.getPackageName() + ".PREFERENCES", Context.MODE_PRIVATE); } catch (Exception e) { //failed to edit shared preferences file showToast(R.string.shared_pref_error); } } return mSharedPreferences; } ``` --- # Shared Preferences Saving to/restoring from the Shared Preferences file. Example (if we chose to store in SharedPreferences) ```java // setting data SharedPreferences.Editor editor = getPrefs().edit(); editor.putInt(CURRENT_TAB_ID_KEY, mTabId); editor.apply(); // have to force the write. // getting data, the last parameter is the default. mTabId = getPrefs().getInt(CURRENT_TAB_ID_KEY, 1); ``` We will see this in Accessibility --- # Shared Preferences Other types you can read/write ```java editor.putBoolean("key", booleanValue); editor.putInt("key", intValue); editor.putString("key", strintValue); editor.putStringSet(key, stringSetValue); ``` --- # End of deck