Files
notes/docs/lectures/mdp/10_storage.md
T

241 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Storage
### Storage Principles
#### App-Specific Requirements
- Store files that are meant for our use only
- Store files that we intend to share with other apps
- e.g. taking a photo
- Store private, primitive data
- Config data, passwords, cookies & keys, etc.
- Store private, structured data
- text messages
#### Mobile Storage Principles
- Efficiency and sharing vs privacy and security
- Limited storage capacity
- Highly personal information stored
- Lots of different data types stored on phone
- Media
- Images, videos, music
> Access to the mail should be protected since this is sensitive user data. However, if a reference to an image attachment is given to an image viewer, that image viewer will not have permission to open the attachment since it has no reason to hold a permission to access all e-mail.
##### Storage Directories
`/system` -> stores Android OS & libraries
`/data` -> where user data is stored (every application is a user)
`/mnt/sdcard` (symlinked as `sdcard`) -> *External* Storage
### Basic Logical Data Storage on Android
##### Different Volumes
###### Internal
- Limited space for app-specific data
- Reliable (not *removable*)
- Soldered RAM
###### External
- Lots of data
- May (or may not) be physically removable
##### Different kinds of data
- Data that is only meaningful for our app should use app-specific storage
- Shareable media content should use shared storage so that other apps can access the content
- Also called scoped storage
##### File-based abstractions
- Shared preferences
- File-based storage
- SQLite database
- Structured data, small binary blobs
![image-20220107004129910](img/ac.png)
## Internal File Storage
Internal data storage is private to the app
- Other apps (and the user) cannot access it
- Kernel-enforced user perms
- Removed on uninstall
- Data is stored in files
- `/data/data/com.example.project/files/`
- Full path not accessible; `files/` becomes the chroot
- This ensures we cannot traverse the directory upwards and gain access to other applications' files
##### Cache Files
`/data/data/com.example.project/cache`
`getCacheDir()` -> gets application’s file directory
Programmer should manage the files
- **May** be deleted when internal storage becomes full
- **Will** be deleted when application is uninstalled
- A *well-behaved* application will delete them when no longer in use
- Recommended to use less than 1MB
#### Shared Preferences
- Stored on a per-application basis
- e.g. saving config info (settings)
- Should not be used for data transfer (use intents and binders instead)
- Primitive data in key-value pairs
- Can have multiple preference files per application
```xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="colourscheme">light</string>
</map>
```
```java
SharedPreferences settings = getSharedPreferences(CONFIG_STORAGE_NAME, 0);
SharedPreferences.Editor editor = settings.editor;
if (settings.getBoolean(MainActivity.CONFIG_THEME, false))
setTheme(...);
else
...
```
#### External Storage
*Legacy name*
- Every Android device provides externally accessible storage (SD card)
- Even phones without a physical SD card must have a **logical representation** of external storage
- Most phones will have one storage device partitioned into `internal / external`
- Phones must do this to conform to the Android API
- *Private* Application files
- *Internal* storage on the external partition
- `getExternalFilesDir()`
- `/sdcard/Android/data/com.example.project/`
- *Public* general files
- World reachable
- Other apps can read and modify these files
- Each *user* has their own *virtual* SD card
- Can be mounted externally (and unmounted/disconnected)
##### Getting Access to External Storage
- Should check state with `Enviroment.getExternalStorageState()`
- It is a separate file system, potentially removable
- `Environment.MEDIA_MOUNTED`
- `Environment.MEDIA_MOUNTED_READ_ONLY`
- Use `getExternalStoragePublicDirectory (String type)` to obtain file for the directory
- Media is stored by type
- Music in the music dir, etc.
- Pass a type to obtain the subdirectory for that type
##### Getting Scoped storage access
- To access files that other apps have created
- We must have `READ_EXTERNAL_STORAGE` permission (in the manifest)
- With this one permission, the app can do whatever (look at downloads, listen to music, look at pictures, etc.)
- This is where scoped storage comes into play
- The files must reside in the media collection (images/music/videos, etc.)
- or request legacy storage `MANAGE_EXTERNAL_STORAGE` (before Android 11)
- Apps only have access to
- App-specific directory on external storage
- Specific types of media that the app has created and contributed to well-defined collections
- If the app takes a picture, it is allowed to store and look at that picture but not allowed to access pictures not taken by that app
- You don't need to request perms to read/write images that we are writing to the MediaStorage
# Android Databases
When the data stored is logically structured, queries are needed to find it based on the structure.
- Android provides local database support
- Can run full SQL queries
- Each app’s databases are local to it
- `Database.db` stored in internal storage
- Powered by SQLite
#### Android and SQLite
- Wrapped in two main classes
- Database represented by `SQLiteDatabase` object
- Allows us to run SQL queries on the database
- `SQLiteOpenHelper`
- Supports the application lifecycle
- `SQLiteOpenHelper` -> `onCreate()`
- Creates the database the **first time** it is called
- This database will exist until the application is installed
- `SQLiteOpenHelper` -> `onUpdate(int oldVer, int newVer)`
- Changing the version number allows the database to be dropped and recreated
- Create an instance of our `SQLiteOpenHelper` subclass
- Get reference to `SQLiteDatabase` using
- `getReadableDatabase()`
- `getWriteableDatabase()`
##### Querying a Database
`void execSQL()` -> used to execute SQL queries that don't return anything
`query()` and `rawQuery()`
- These return a Cursor object pointing to the results
`Cursor rawQuery (String sql, String[] selectionArgs)`
###### Cursors
- Provide random access to results of a query
- Enable us to enumerate the rows returned by the query
- `moveToFirst()`, `moveToNext()`
- `getString(colIndex)`, `getInt(colIndex)`
- Have a `close()` method to close the query when finished
We can pass cursors to other applications
###### CursorLoader
- A query may last some time
- Database may be large
- May be in a different process
- Don’t block the main thread
- `CursorLoader`
- Populates views asynchronously
- Auto-updating
(deprecated)
#### Data-Driven Views
- *Connect* a cursor to a `CursorAdapter` and a `ListView`
- Think mapping rows of a database to which entry in the list
- Each row must have an ID field
- `RecyclerView`
- An optimised, flexible version of the above
- Only creates views for visible data
- As the user scrolls, more data is added
- We can define our own adaptor
### Database Abstraction
Abstraction of database architecture
- Easier to update storage code
- Expose column indices as static class variables
- `c.getInt(0)` &#10007;
- `c.getInt(DBHelper.NAME)` &#10003;
- Helper methods keep database internals from *leaking* into other classes
- Return a collection of results rather than the cursor
- **Sanitise user inputs**
- SQL injections still apply