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 handleMessage(Message msg)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 onCreate()120 public void onCreate() { 121 mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 122 123 // Display a notification about us starting. 124 showNotification(); 125 } 126 127 @Override onDestroy()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 onBind(Intent intent)141 public IBinder onBind(Intent intent) { 142 return mMessenger.getBinder(); 143 } 144 145 /** 146 * Show a notification while this service is running. 147 */ showNotification()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