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