Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.apis.app;
     18 
     19 import android.app.Notification;
     20 import android.app.NotificationManager;
     21 import android.app.PendingIntent;
     22 import android.app.Service;
     23 import android.content.Intent;
     24 import android.os.Binder;
     25 import android.os.Handler;
     26 import android.os.IBinder;
     27 import android.os.Message;
     28 import android.os.Messenger;
     29 import android.os.RemoteException;
     30 import android.util.Log;
     31 import android.widget.Toast;
     32 
     33 import java.util.ArrayList;
     34 
     35 // Need the following import to get access to the app resources, since this
     36 // class is in a sub-package.
     37 import com.example.android.apis.R;
     38 import com.example.android.apis.app.RemoteService.Controller;
     39 
     40 /**
     41  * This is an example of implementing an application service that uses the
     42  * {@link Messenger} class for communicating with clients.  This allows for
     43  * remote interaction with a service, without needing to define an AIDL
     44  * interface.
     45  *
     46  * <p>Notice the use of the {@link NotificationManager} when interesting things
     47  * happen in the service.  This is generally how background services should
     48  * interact with the user, rather than doing something more disruptive such as
     49  * calling startActivity().
     50  */
     51 //BEGIN_INCLUDE(service)
     52 public class MessengerService extends Service {
     53     /** For showing and hiding our notification. */
     54     NotificationManager mNM;
     55     /** Keeps track of all current registered clients. */
     56     ArrayList<Messenger> mClients = new ArrayList<Messenger>();
     57     /** Holds last value set by a client. */
     58     int mValue = 0;
     59 
     60     /**
     61      * Command to the service to register a client, receiving callbacks
     62      * from the service.  The Message's replyTo field must be a Messenger of
     63      * the client where callbacks should be sent.
     64      */
     65     static final int MSG_REGISTER_CLIENT = 1;
     66 
     67     /**
     68      * Command to the service to unregister a client, ot stop receiving callbacks
     69      * from the service.  The Message's replyTo field must be a Messenger of
     70      * the client as previously given with MSG_REGISTER_CLIENT.
     71      */
     72     static final int MSG_UNREGISTER_CLIENT = 2;
     73 
     74     /**
     75      * Command to service to set a new value.  This can be sent to the
     76      * service to supply a new value, and will be sent by the service to
     77      * any registered clients with the new value.
     78      */
     79     static final int MSG_SET_VALUE = 3;
     80 
     81     /**
     82      * Handler of incoming messages from clients.
     83      */
     84     class IncomingHandler extends Handler {
     85         @Override
     86         public void handleMessage(Message msg) {
     87             switch (msg.what) {
     88                 case MSG_REGISTER_CLIENT:
     89                     mClients.add(msg.replyTo);
     90                     break;
     91                 case MSG_UNREGISTER_CLIENT:
     92                     mClients.remove(msg.replyTo);
     93                     break;
     94                 case MSG_SET_VALUE:
     95                     mValue = msg.arg1;
     96                     for (int i=mClients.size()-1; i>=0; i--) {
     97                         try {
     98                             mClients.get(i).send(Message.obtain(null,
     99                                     MSG_SET_VALUE, mValue, 0));
    100                         } catch (RemoteException e) {
    101                             // The client is dead.  Remove it from the list;
    102                             // we are going through the list from back to front
    103                             // so this is safe to do inside the loop.
    104                             mClients.remove(i);
    105                         }
    106                     }
    107                     break;
    108                 default:
    109                     super.handleMessage(msg);
    110             }
    111         }
    112     }
    113 
    114     /**
    115      * Target we publish for clients to send messages to IncomingHandler.
    116      */
    117     final Messenger mMessenger = new Messenger(new IncomingHandler());
    118 
    119     @Override
    120     public void onCreate() {
    121         mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    122 
    123         // Display a notification about us starting.
    124         showNotification();
    125     }
    126 
    127     @Override
    128     public void onDestroy() {
    129         // Cancel the persistent notification.
    130         mNM.cancel(R.string.remote_service_started);
    131 
    132         // Tell the user we stopped.
    133         Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
    134     }
    135 
    136     /**
    137      * When binding to the service, we return an interface to our messenger
    138      * for sending messages to the service.
    139      */
    140     @Override
    141     public IBinder onBind(Intent intent) {
    142         return mMessenger.getBinder();
    143     }
    144 
    145     /**
    146      * Show a notification while this service is running.
    147      */
    148     private void showNotification() {
    149         // In this sample, we'll use the same text for the ticker and the expanded notification
    150         CharSequence text = getText(R.string.remote_service_started);
    151 
    152         // The PendingIntent to launch our activity if the user selects this notification
    153         PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
    154                 new Intent(this, Controller.class), 0);
    155 
    156         // Set the info for the views that show in the notification panel.
    157         Notification notification = new Notification.Builder(this)
    158                 .setSmallIcon(R.drawable.stat_sample)  // the status icon
    159                 .setTicker(text)  // the status text
    160                 .setWhen(System.currentTimeMillis())  // the time stamp
    161                 .setContentTitle(getText(R.string.local_service_label))  // the label of the entry
    162                 .setContentText(text)  // the contents of the entry
    163                 .setContentIntent(contentIntent)  // The intent to send when the entry is clicked
    164                 .build();
    165 
    166         // Send the notification.
    167         // We use a string id because it is a unique number.  We use it later to cancel.
    168         mNM.notify(R.string.remote_service_started, notification);
    169     }
    170 }
    171 //END_INCLUDE(service)
    172