MessengerService.java revision bae0f4fd87cb2a3eacb30a06840465ad04b2de53
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
17package com.example.android.apis.app;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
22import android.app.Service;
23import android.content.Intent;
24import android.os.Binder;
25import android.os.Handler;
26import android.os.IBinder;
27import android.os.Message;
28import android.os.Messenger;
29import android.os.RemoteException;
30import android.util.Log;
31import android.widget.Toast;
32
33import 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.
37import com.example.android.apis.R;
38import 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)
52public 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        // Set the icon, scrolling text and timestamp
153        Notification notification = new Notification(R.drawable.stat_sample, text,
154                System.currentTimeMillis());
155
156        // The PendingIntent to launch our activity if the user selects this notification
157        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
158                new Intent(this, Controller.class), 0);
159
160        // Set the info for the views that show in the notification panel.
161        notification.setLatestEventInfo(this, getText(R.string.remote_service_label),
162                       text, contentIntent);
163
164        // Send the notification.
165        // We use a string id because it is a unique number.  We use it later to cancel.
166        mNM.notify(R.string.remote_service_started, notification);
167    }
168}
169//END_INCLUDE(service)
170