Files
notes/docs/lectures/mdp/12_content_providers.md
T

165 lines
5.2 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.
# Content Providers - Storage
Access to data is restricted to the app that owns it
- Database is usually located in internal app-specific storage
- If we want other apps to access our data, or we want to access other apps’ data, or we want to be notified when data has changed, we must use a content provider
Content providers expose data / content to other applications in a structured manner
- Fundamentally IPC via Binder and ashmem (Android shared memory) with a well-defined (database-like) interface
#### System Content Providers
Content providers manage data for:
**Browser**: bookmarks, history
**Call Log**: Telephone usage
**Contacts**: Contact data, contacts for other apps, e.g. WhatsApp
**Media**: Media metadata database
**User Dictionary**: database for predictive spelling
###### Storage Access Framework
Is an abstraction of *documents*
- Restricted access to external storage
- Enumerated by the system content object picker
![image-20220107180058110](img/af.png)
A content provider is mostly used for making content available outside your application, as using it to get data is now done by the repository.
###### How to use it?
- Create our own by sub-classing `ContentProvider`
- Must add it in the manifest
- Or add/query data via an existing content provider
### Data Model
Very similar to a relational database table
- A collection of records
- Support for read/write
- Support for typical database operations
- CRUD - **C**reate **R**ead **U**pdate **D**elete
Records are stored in rows, with each column providing different data fields
- Each record has a numeric id (in the field ID) that uniquely identifies it
- Tables exposed via URI
- This is a further abstraction
![image-20220107180837589](img/ag.png)
Applications query the content provider, which maps the requests to the underlying database. This can be SQLite or Room (doesn’t really matter to the application)
### Querying a Content Provider
Content Providers **identify data** sets through **URIs**
- `content://authority/path/id`
- **content**: Data managed by a content provider
- **authority**: ID for the Content provider
- A fully qualified class name, e.g. `com.example.project`
- **path**: 0 or more segments indicating the subset of data to be requested
- e.g. table name
- A RESTful resource philosophy
- **id**: specific record (row) being accessed
`/email/2021/Nov/17` -> would retrieve all emails received on Nov 17th 📅
###### Content Resolver
- Manages and supports content provider access
- How to service a request for content
- Similar to `ServiceManager`
- Enables Content Providers to be used across multiple applications
- Can observe a content provider to be informed of real-time modifications
- e.g. `contentResolver` monitors the path and can notify if a new email pops up ✉
Full URI: `ContactsContract.Contact.CONTENT_URI = "content://com.android.contacts/contacts/"`
`ContentResolver.query(...)`
- Returns a cursor instance for accessing results
- Cursor is a pointer to a `cursorWindow`
- A read-only reference to shared memory
- Allocated by ashmem
- Retrieved via Binder
- Max `CursorWindow` size is 2 Mb
###### Example of Querying Contacts
- To access / modify requires a permission
- `android.permission.READ_CONTACTS`
- `android.permission.WRITE_CONTACTS`
- Contacts has 3 components
- Data
- Rows (mime-typed) that can hold personal info
- Raw Contacts
- A contact for a given person from a given system
- Gmail contact, Facebook contact, etc.
- Associated with data entries
- Contacts
- Aggregated raw contacts
- Single view of a *person*
##### Modifying a Content Provider
`Uri insert (Uri uri, ContentValues values)`
Returns the URI of the newly inserted item
`int update(Uri uri, ContentValues values, String where, String[] selectionArgs)`
###### Parameters
**uri**: the *table* we want to modify
**content values**: values for the new row or key/value pairs where the key is the column name
#### Creating a content Provider
- Implement a storage system for the data
- Structured data, can be SQLite or Room
- Media & blobs
- Implement a content provider
- query, add, update, insert, etc.
- onCreate
- When content provider is instantiated, needs to instantiate the internal storage (create the table)
- getType
- single items, multiple items, mime type
- Tell Android we are a provider
- Declare in the manifest
#### Contract
- Defines metadata pertaining to the provider
- Constant definitions that are exposed to developers via a compiled .jar file
- Authority
- URI
- Meta-data
- Column names
#### URI Matching
All of these methods take a URI as the first parameter
- The object will need to parse it to know what to return
`android.content.UriMatcher`
- Provides mapping between abstraction of contract class to concrete db implementation
- Does the calling app want all the data from the table or just a row?
- `content://authority/tablename/`
- whole table
- `content://authority/tablename/1`
- row
- Or a virtual table (joins across various underlying resources)