MessengerService.java

← Back

The file containing the source code shown below is located in the corresponding directory in <sdk>/samples/android-<version>/...

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.example.android.apis.app;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;

// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import com.example.android.apis.R;
import com.example.android.apis.app.RemoteService.Controller;

/**
 * This is an example of implementing an application service that uses the
 * {@link Messenger} class for communicating with clients.  This allows for
 * remote interaction with a service, without needing to define an AIDL
 * interface.
 *
 * <p>Notice the use of the {@link NotificationManager} when interesting things
 * happen in the service.  This is generally how background services should
 * interact with the user, rather than doing something more disruptive such as
 * calling startActivity().
 */

public class MessengerService extends Service {
   
/** For showing and hiding our notification. */
   
NotificationManager mNM;
   
/** Keeps track of all current registered clients. */
   
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
   
/** Holds last value set by a client. */
   
int mValue = 0;

   
/**
     * Command to the service to register a client, receiving callbacks
     * from the service.  The Message's replyTo field must be a Messenger of
     * the client where callbacks should be sent.
     */

   
static final int MSG_REGISTER_CLIENT = 1;

   
/**
     * Command to the service to unregister a client, ot stop receiving callbacks
     * from the service.  The Message's replyTo field must be a Messenger of
     * the client as previously given with MSG_REGISTER_CLIENT.
     */

   
static final int MSG_UNREGISTER_CLIENT = 2;

   
/**
     * Command to service to set a new value.  This can be sent to the
     * service to supply a new value, and will be sent by the service to
     * any registered clients with the new value.
     */

   
static final int MSG_SET_VALUE = 3;

   
/**
     * Handler of incoming messages from clients.
     */

   
class IncomingHandler extends Handler {
       
@Override
       
public void handleMessage(Message msg) {
           
switch (msg.what) {
               
case MSG_REGISTER_CLIENT:
                    mClients
.add(msg.replyTo);
                   
break;
               
case MSG_UNREGISTER_CLIENT:
                    mClients
.remove(msg.replyTo);
                   
break;
               
case MSG_SET_VALUE:
                    mValue
= msg.arg1;
                   
for (int i=mClients.size()-1; i>=0; i--) {
                       
try {
                            mClients
.get(i).send(Message.obtain(null,
                                    MSG_SET_VALUE
, mValue, 0));
                       
} catch (RemoteException e) {
                           
// The client is dead.  Remove it from the list;
                           
// we are going through the list from back to front
                           
// so this is safe to do inside the loop.
                            mClients
.remove(i);
                       
}
                   
}
                   
break;
               
default:
                   
super.handleMessage(msg);
           
}
       
}
   
}

   
/**
     * Target we publish for clients to send messages to IncomingHandler.
     */

   
final Messenger mMessenger = new Messenger(new IncomingHandler());

   
@Override
   
public void onCreate() {
        mNM
= (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

       
// Display a notification about us starting.
        showNotification
();
   
}

   
@Override
   
public void onDestroy() {
       
// Cancel the persistent notification.
        mNM
.cancel(R.string.remote_service_started);

       
// Tell the user we stopped.
       
Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
   
}

   
/**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */

   
@Override
   
public IBinder onBind(Intent intent) {
       
return mMessenger.getBinder();
   
}

   
/**
     * Show a notification while this service is running.
     */

   
private void showNotification() {
       
// In this sample, we'll use the same text for the ticker and the expanded notification
       
CharSequence text = getText(R.string.remote_service_started);

       
// Set the icon, scrolling text and timestamp
       
Notification notification = new Notification(R.drawable.stat_sample, text,
               
System.currentTimeMillis());

       
// The PendingIntent to launch our activity if the user selects this notification
       
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
               
new Intent(this, Controller.class), 0);

       
// Set the info for the views that show in the notification panel.
        notification
.setLatestEventInfo(this, getText(R.string.remote_service_label),
                       text
, contentIntent);

       
// Send the notification.
       
// We use a string id because it is a unique number.  We use it later to cancel.
        mNM
.notify(R.string.remote_service_started, notification);
   
}
}