207 lines
7.2 KiB
Markdown
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
|
|
|
|

|
|
|
|
### 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
|
|
|
|

|
|
|
|
| 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
|