Understanding Local Services

Local services are services that are started via Context.startService(). Once started, these types of services will continue to run until a client calls Context.stopService() on the service or the service itself calls stopSelf(). Note that when Context.startService() is called, the system will instantiate the service and call the service's onStart() method. Keep in mind that calling Context.startService() after the service has been started (that is, while it's running) will not result in another instance of the service, but doing so will invoke the service's onStart() method. Here are a couple examples of local services:

• A service to retrieve data over the network (such as the Internet) based on a timer (to either upload or download information)

• A task-executor service that lets your application's activities submit jobs and queue them for processing

Listing 8-9 demonstrates a local service by implementing a service that executes background tasks. The listing contains all of the artifacts required to create and consume the service: BackgroundService.java, the service itself; MainActivity.java, an activity class to call the service; and main.xml, a layout file for the activity.

Listing 8-9. Implementing a Local Service // BackgroundService.java import android.app.Notification; import android.app.NotificationManager; import android.app.Pendinglntent; import android.app.Service; import android.content.Intent; import android.os.IBinder;

public class BackgroundService extends Service {

private NotificationManager notificationMgr; ^Override public void onCreate() { super.onCreate();

notificationMgr =(NotificationManager)getSystemService( NOTIFICATION_SERVICE);

displayNotificationMessage("starting Background Service");

Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService"); thr.start();

class ServiceWorker implements Runnable {

// do background processing here...

// stop the service when done... // BackgroundService.this.stopSelf();

^Override public void onDestroy() {

displayNotificationMessage("stopping Background Service"); super.onDestroy();

^Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId);

^Override public IBinder onBind(Intent intent) { return null;

private void displayNotificationMessage(String message) {

Notification notification = new Notification(R.drawable.note, message,System.currentTimeMillis());

Pendinglntent contentlntent = PendingIntent.getActivity(this, 0,new Intent(this, MainActivity.class), 0);

notification.setLatestEventInfo(this, "Background Service",message, contentIntent);

notificationMgr.notify(R.string.app_notification_id, notification);

// MainActivity.java import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

public class MainActivity extends Activity {

private static final String TAG = "MainActivity";

^Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); setContentView(R.layout.main);

Log.d(TAG, "starting service");

Button bindBtn = (Button)findViewById(R.id.bindBtn); bindBtn.setOnClickListener(new OnClickListener(){

^Override public void onClick(View arg0) {

startService(new Intent(MainActivity.this, BackgroundService.class));

Button unbindBtn = (Button)findViewById(R.id.unbindBtn); unbindBtn.setOnClickListener(new OnClickListener(){

^Override public void onClick(View arg0) {

stopService(new Intent(MainActivity.this, BackgroundService.class));

// main.xml (layout file for MainActivity.java) <?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<Button android:id="@+id/bindBtn"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Bind" />

<Button android:id="@+id/unbindBtn"





Note that Listing 8-9 uses an activity to interface with the service, but any component in your application can use the service. This includes other services, activities, generic classes, and so on. The example creates a user interface with two buttons, labeled Bind and UnBind. Clicking the Bind button will start the service by calling startService(); clicking UnBind will stop the service by calling stopService(). Now let's talk about the meat of the example: the BackgroundService.

The BackgroundService is a typical example of a service that is used by the components of the application that is hosting the service. In other words, the application that is running the service is also the only consumer. Because the service does not support clients from outside its process, the service is a local service. And because it's a local service as opposed to a remote service, it returns null in the bind() method. Therefore, the only way to bind to this service is to call Context.startService(). The critical methods of a local service are: onCreate(), onStart(), stop*(), and onDestroy().

In the onCreate() method of the BackgroundService, we create a thread that does the service's heavy lifting. We need the application's main thread to deal with user interface activities, so we delegate the service's work to a secondary thread. Also note that we create and start the thread in onCreate() rather than onStart(). We do this because onCreate() is called only once, and we want the thread to be created only once during the life of the service. onStart() can be called more than once, so it doesn't suit our needs here. We don't do anything useful in the implementation of the thread's run method, but this would be the place to make an HTTP call, query a database, and so on.

The BackgroundService also uses the NotificationManager class to send notifications to the user when the service is started and stopped. This is one way for a local service to communicate information back to the user. To send notifications to the user, you obtain the notification manager by calling getSystemService(NOTIFICATION_SERVICE). Messages from the notification manager appear in the status bar.

To run the example, you need to create the BackgroundService.java service, the MainActivity.java activity class, and the main.xml layout file. You'll also need to create an icon named note and place it within your project's drawable folder. Plus, you need an application-level unique ID (integer) for the notification manager. You can create a unique ID by adding a dummy string constant to your string resources (a string at res/values/strings.xml). The unique ID is passed to the notification manager when you call the notify() method. In our example, we use the following:

<string name="app_notification_id">notification_id</string>

This concludes our discussion of local services. Let's dissect AIDL services—the more complicated type of service.

0 0

Post a comment