Service in a separate process
When an Android service runs on its own process, it runs in an independent process, with its own address space, making the communication with the main process UI thread harder to implement the following:
<service android:name="SynonymService" android:process=":my_synonnym_search_proc" android:icon="@drawable/icon" android:label="@string/service_name" > </service>
To implement a service in a different process, we need to use an inter-process communication (IPC) technique to send messages between your application and the service.
Note
IPC is the activity of sharing data across multiple processes, usually using a well-defined communication protocol. It typically has a process that acts as the client and a process that acts as the server.
There are two technologies available on the Android SDK to implement this, as follows:
- AIDL (Android Interface Definition Language): This allows you to define an interface over a set of primitive types. It allows you create multithreaded processing services, but it adds other levels of complexity to your implementation. This is only recommended to advanced programmers.
- Messenger: This is a simple interface that creates a queue of work for you in the service side. This executes all the tasks sequentially on single thread managed by a
Handler
.
We haven't given more details about these techniques yet; however, an example of this construct is going to be presented later in a more advanced chapter where all the concepts involved are more mature.
Broadcast receiver concurrent issues
This building block is a component that subscribes to system and application events and is notified when these events occur on the system. The broadcast receivers are defined statically in the application manifest or dynamically via the Context.registerReceiver()
.
The broadcast received is activated though the onReceive()
callback and this method runs on the main thread, blocking another Android component from running if we try to execute time-consuming tasks.
Once onReceive()
finishes, the system considers the object inactive and can release the resources attached to this instance and recycle the whole object. This behavior has a tremendous impact on what we can do inside, because if we hand over some processing to a concurrent thread, the resources that belong to BroadcastReceiver
might be recycled and are no longer available, or in an extreme case, the process could be killed if there were no important components running on it.
Tip
Android version 11 introduced the goAsync()
method on the broadcast receiver to keep the broadcast active after returning from the onReceive()
function.
Android concurrency constructs
The good news is that the Android platform provides specific constructs to address the concurrency general issues and to solve the specific problems presented by Android.
There are constructs that allow us to defer tasks to run later on the main thread, communicate easily between cooperating threads, and issue work to the managed pools of worker threads and reintegrate the results back in the main thread.
There are solutions to the constraints of the Activity lifecycle, both for medium-term operations that closely involve the user interface and longer-term work that must be completed even if the user leaves the application.
While some of these constructs were only introduced with newer releases of the Android platform, they are available through the support libraries, and with a few exceptions, the examples in this book target devices that run API level 8 (Android 2.2) and higher versions.