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