An app can interact with a Service in one of three ways. It can start the Service by calling
startService(), it can bind to the Service by calling
bindService(), or since Android 5.0 it can use the
JobScheduler to run a Service.
bindService() take an Intent as an argument.
Unlike Activities, where the user can immediately see which Activity has started, calling
bindService() with an implicit Intent is a security hazard, as you cannot be sure which service will respond, and the user has no way to tell.
Important: never pass an implicit Intent to
bindService(). In Android 5.0 (API level 21) onwards,
bindService()throws an exception if called with an implicit Intent.
Like Activities, Services can be secured by adding an appropriate permission to the
<service> element in the app’s
AndroidManifest.xml file. This ensures that only apps with that permission can start or bind to the Service.
<manifest …> <application …> <service android:name="com.example.myamazingapp.SomeService" android:permission="com.example.myamazingapp.SOME_PERMISSION"> … </service> </application> </manifest>
Given the potential security hazard with Services and implicit Intents, you should carefully consider whether your Service should specify an Intent Filter, and even whether your Service should be public at all. If your Service does not specify an Intent Filter then it can only be accessed via explicit Intents.
Securing Bound Services
A call to
bindService() returns an
IBinder object from the Service (indirectly since
bindService() is asynchronous). The
IBinder object provides the interface by which the component can make synchronous (RPC like) method invocations on the Bound Service.
The actual interface exposed by the Service is specific to that Service, and the methods available are not declared within the app’s
AndroidManifest.xml file, so they cannot be given their own permissions via the manifest. They do however inherit permissions from the enclosing service (as specified in the app’s
It is best therefore to structure your app so that the methods of a Bound Service do not need specific permission checks.
However, if methods of the bound interface do require specific permission checks, then this can be done programatically by calling
checkCallingPermission() with the required permission.
This will return whether the component that is invoking the method of the Bound Service has the specified permission, but doing this is potentially error prone, as you may miss a path through your code and fail to check the caller’s permission in all cases.
If at all possible specify Bound Service permissions via the app’s
AndroidManifest.xml file. If different methods provided by a Bound Service require different permission checks, consider splitting the Bound Service into several separate Services, as this is possibly an indication that the methods do not logically belong together.
Properly securing Bound Services is beyond the scope of this introductory course.
In Android 5.0 (API level 21) the
JobScheduler was introduced. This is intended for Services which an app runs in its own process (as jobs), and the
JobScheduler will aim to schedule the jobs in an intelligent way.
JobService must be given the following permission in the
<manifest …> <application …> <service android:name="com.example.myamazingapp.SomeJobService" android:permission="android.permission.BIND_JOB_SERVICE"> … </service> </application> </manifest>
BIND_JOB_SERVICE is defined with the signature protection level, and therefore can only be granted to the Android platform itself. This means only the
JobScheduler is able to run the
© University of Southampton 2017