Content providers offer two distinct attributes: readPermission
and writePermission
:
<provider
android:name='.SekritProvider'
android:authorities='vnd.tla.sekrits.SekritProvider'
android:readPermission='vnd.tla.sekrits.SEE SEKRITS'
android:writePermission='vnd.tla.sekrits.MOD SEKRITS' />
In this case, readPermission
controls access to querying the content provider, while writePermission
controls access to insert, update, or delete data in the content provider.
Enforcing Permissions Elsewhere
In your code, you have two additional ways to enforce permissions.
Your services can check permissions on a per-call basis via checkCallingPermission()
. This returns PERMISSION GRANTED
or PERMISSION DENIED
, depending on whether the caller has the permission you specified. For example, if your service implements separate read and write methods, you could get the effect of readPermission
and writePermission
in code by checking those methods for the permissions you need from Java.
Also, you can include a permission when you call sendBroadcast()
. This means that eligible receivers must hold that permission; those without the permission are ineligible to receive it. For example, the Android subsystem presumably includes the RECEIVE SMS
permission when it broadcasts that an SMS message has arrived — this will restrict the receivers of that intent to be only those authorized to receive SMS messages.
May I See Your Documents?
There is no automatic discovery of permissions at compile time; all permission failures occur at runtime. Hence, it is important that you document the permissions required for your public APIs, including content providers, services, and activities intended for launching from other activities. Otherwise, the programmers attempting to interface with your application will have to find out the permission rules by trial and error.
Furthermore, you should expect that users of your application will be prompted to confirm any permissions your application says it needs. Hence, you need to document for your users what they should expect, lest they get confused by the question posed by the phone and elect to not install or use your application.
CHAPTER 30
Creating a Service
As noted previously, Android services are for long-running processes that may need to keep running even when decoupled from any activity. Examples include playing music even if the “player” activity gets garbage- collected, polling the Internet for RSS/Atom feed updates, and maintaining an online chat connection even if the chat client loses focus due to an incoming phone call.
Services are created when manually started (via an API call) or when some activity tries connecting to the service via inter-process communication (IPC). Services will live until no longer needed and if RAM needs to be reclaimed. Running for a long time isn’t without its costs, though, so services need to be careful not to use too much CPU or keep radios active much of the time, or else the service causes the device’s battery to get used up too quickly.
This chapter covers how you can create your own services; the next chapter covers how you can use such services from your activities or other contexts. Both chapters will analyze the Service/WeatherPlus
sample application, with this chapter focusing mostly on the WeatherPlusService
implementation. WeatherPlusService
extends the weather-fetching logic of the original Internet/Weather
sample, by bundling it in a service that monitors changes in location, so the weather is updated as the emulator is “moved”.
Service with Class
Creating a service implementation shares many characteristics with building an activity. You inherit from an Android-supplied base class, override some lifecycle methods, and hook the service into the system via the manifest.
The first step in creating a service is to extend the Service
class, in our case with our own WeatherPlusService
subclass.
Just as activities have onCreate()
, onResume()
, onPause()
and kin, Service
implementations can override three different lifecycle methods:
1. onCreate()
, which, as with activities, is called when the service process is created
2. onStart()
, which is called when a service is manually started by some other process, versus being implicitly started as the result of an IPC request (discussed more in Chapter 31)
3. onDestroy()
, which is called as the service is being shut down.
Common startup and shutdown logic should go in onCreate()
and onDestroy()
; onStart()
is mostly if your service needs data passed into it from the starting process and you don’t wish to use IPC.
For example, here is the onCreate()
method for WeatherPlusService
:
@Override
public void onCreate() {
super.onCreate();
client = new DefaultHttpClient();
format = getString(R.string.url);
myLocationManager =
(LocationManager)getSystemService (Context.LOCATION_SERVICE);
myLocationManager.requestLocationUpdates('gps', 10000,
10000.0f, onLocationChange);
}
First, we chain upward to the superclass, so Android can do any setup work it needs to have done. Then we initialize our HttpClient
and format string as we did in the Weather demo. We then get the LocationManager
instance for our application and request to get updates as our location changes,