Files
notes/docs/lectures/mdp/06_communication.md
T

207 lines
7.2 KiB
Markdown

# Services - Communication
How can an **activity** communicate with a **service**?
> By sending one or more intents
>
> - This is done by calling `onStartCommand` multiple times
How should the **service communicate** with the **user**?
> This is done through notifications
How should the **service** **communicate** with the **activity**?
> For example: sending an email or playing an MP3
>
> For this we use **binding**
How does the **service** guarantee that **work is completed**?
> By using life-cycles
## Notifications
**Notifications** are intended to inform users about events from an application.
- Potentially a source of disruption.
- Caused by something in the background
- Require the user's attention
- Adversely affect task completion time (of the user)
- Impact the emotional & effective state of the user
### Cross-Platform Principles
###### Avoid
- An app the user has never opened
- Messages that encourage the user to return to an app, but provide no value
- Operations that don't require user involvement, like syncing information
- Error states from which the app could recover without user interaction
- Personal/sensitive/confidential information
###### Aim To
- Create succinct, easy-to-read notifications that provide useful information
- Provide intuitive, beneficial actions
###### Actioned via
- Showing a status bar icon
- Appearing on the lock screen
- Playing a sound/vibration
- Peeking onto the current screen
### Relationship to Services
- Notify the user that the service is operating / has done something
- Service does not have a UI
- The notification is an invitation for the user to return to the application
- This is because the original activity might not still be running
- Notifications are maintained by the service
- Can specify an activity to launch if the user taps on it via a `PendingIntent`
- 'return' to the activity that spawned the service
- A `PendingIntent` itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that even if the owning application's process has been killed, the `PendingIntent` itself will remain usable from other processes that have been given it.
- Can control the service via buttons in the notification
- Deliver Intents to the service (`startService`/`onStartCommand`), this works because the service is a singleton object
### Activity/Service Navigation and State
###### Ways back to the activity
- Via service hosted notification
- Via task manager
- Via launcher
###### Depending on the owning process, the activity might have been
- Destroyed
- Finished
###### The activity is ephemeral (lasting a short amount of time)
- Incorrect to store server state in activity instance state
- What has the service been doing in the meantime?
- Interrogate service to retrieve non-instance state `onCreate`, `onBind`
- Start or stop the service (is it still necessary/needed)
## Service Lifecycle
Two ways of spawning a service
- Started (loosely coupled)
- Send an intent to explicitly start the service with `startService()`
- Will run/exist in the background indefinitely / kills itself
- Useful for consistently checking emails
- **Does not return a result**
- Explicitly stop the service with `stopService()`
- Bound (tightly coupled)
- Bind to a service using `bindService()`
- Will run while activities are bound to it
- Provides a programmatic interface for activities to communicate with the service
In both cases, if the service is not running, it will be created.
- Different responsibilities for the lifecycle
- If I start it, I have to stop it
- If the OS starts it, the OS stops it when it decides to
- Two conflated purposes
- *Manage* the service lifecycle
- *Bind* to the service for communication
- *Only* Bind = automatic lifecycle
- *Only* Start = manual lifecycle, intent communication
- Start *and* Bind = manual lifecycle, programmatic interface
![img](img/n.png)
### Terminating Services
A service runs in the background indefinitely
- Even if the component that started it is destroyed / finished
Termination of service
- Self-termination (calling `stopSelf()`)
- `stopService()` via an intent
- System termination
- i.e. memory storage
Avoiding termination
- Foregrounding a service
- This is something the user should really know about or is aware of
- Is treated as important as a foreground activity, `startForeground()`
- Background services are vulnerable
- In Android 8.0+ - background services can and will be stopped by the system, enforcing a Cron / job scheduling model.
A service runs in the background indefinitely
- Indefinitely = a few minutes
- Even if the component that started it is destroyed
- `onStartCommand()` return value determines how the service should be continued if it is destroyed
`START_NOT_STICKY`
- After `onStartCommand()` returns, do not recreate the service unless there are intents to deliver
`START_STICKY`
- Recreate the service and call `onStartCommand()` again, but do not redeliver the last intent.
`START_REDELIVER_INTENT`
- Recreate the service and call `onStartCommand()` again; deliver the last intent
- Immediately resume the previous job, i.e. downloading a file
## Foreground Services and Notifications
Foreground services perform operations that are *noticeable* to the user
- Foreground services are app processes that run in the background while the user is not directly interacting with the app.
- Android requires users to be made aware of this with a non-dismissible notification
- Because the user can't dismiss the notification, you should provide an action (button) for the user to stop the service.
###### Examples
- A music player app
- A notification will continually show song progress, play/pause, etc.
## Communicating with Services
Bind to the service
- If not explicitly started, will be started by the OS
- Provide an interface for clients (Activities) to interact with a service
- Aims to be fast and stable
- Binder object asynchronously provides a reference to the service that we can call methods on
- via `ServiceConnection`
- Binder object forms the basis of the programmatic interface for **activities**.
- i.e. we can use this object to call methods on the service
- Asynchronous as we have to wait for the OS to create the service
![img](img/p.png)
| Activity | Service |
| :--------------------: | :-----: |
| Component | Service |
| Service Connection | IBinder |
| `onServiceConnected()` | |
What this binder object allows us to do:
We can use `ServiceConnection` to call methods on the service and receive results.
### Activity/Service Communication
- Extending the Binder class
- Return an interface via the `inBind()` method
- Only for a Service used by the same application
- Local services only
- Make method calls within the same JVM (Android runtime)
- Who drives communication?
- Activity - regularly polls the service for information
- Service
- Maintain a list of callbacks using Binder objects to identify activity clients
- Enumerate and call each activity via a callback interface