# 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