TileService.java revision 8f7f3184d55850b1c4d2036319794151f564e9c0
1/* 2 * Copyright (C) 2015 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 */ 16package android.service.quicksettings; 17 18import android.app.Dialog; 19import android.app.Service; 20import android.content.Intent; 21import android.os.Handler; 22import android.os.IBinder; 23import android.os.Looper; 24import android.os.Message; 25import android.os.RemoteException; 26import android.view.WindowManager; 27 28/** 29 * A QSTileService provides the user a tile that can be added to Quick Settings. 30 * Quick Settings is a space provided that allows the user to change settings and 31 * take quick actions without leaving the context of their current app. 32 * 33 * <p>The lifecycle of a QSTileService is different from some other services in 34 * that it may be unbound during parts of its lifecycle. Any of the following 35 * lifecycle events can happen indepently in a separate binding/creation of the 36 * service.</p> 37 * 38 * <ul> 39 * <li>When a tile is added by the user its QSTileService will be bound to and 40 * {@link #onTileAdded()} will be called.</li> 41 * 42 * <li>When a tile should be up to date and listing will be indicated by 43 * {@link #onStartListening()} and {@link #onStopListening()}.</li> 44 * 45 * <li>When the user removes a tile from Quick Settings {@link #onStopListening()} 46 * will be called.</li> 47 * </ul> 48 * <p>QSTileService will be detected by tiles that match the {@value #ACTION_QS_TILE} 49 * and require the permission "android.permission.BIND_QUICK_SETTINGS_TILE". 50 * The label and icon for the service will be used as the default label and 51 * icon for the tile. Here is an example QSTileService declaration.</p> 52 * <pre class="prettyprint"> 53 * {@literal 54 * <service 55 * android:name=".MyQSTileService" 56 * android:label="@string/my_default_tile_label" 57 * android:icon="@drawable/my_default_icon_label" 58 * android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> 59 * <intent-filter> 60 * <action android:name="android.service.quicksettings.action.QS_TILE" /> 61 * </intent-filter> 62 * </service>} 63 * </pre> 64 * 65 * @see Tile Tile for details about the UI of a Quick Settings Tile. 66 */ 67public class TileService extends Service { 68 69 /** 70 * Action that identifies a Service as being a QSTileService. 71 */ 72 public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE"; 73 74 private final H mHandler = new H(Looper.getMainLooper()); 75 76 private boolean mListening = false; 77 private Tile mTile; 78 private IBinder mToken; 79 80 /** 81 * Called when the user adds this tile to Quick Settings. 82 * <p/> 83 * Note that this is not guaranteed to be called between {@link #onCreate()} 84 * and {@link #onStartListening()}, it will only be called when the tile is added 85 * and not on subsequent binds. 86 */ 87 public void onTileAdded() { 88 } 89 90 /** 91 * Called when the user removes this tile from Quick Settings. 92 */ 93 public void onTileRemoved() { 94 } 95 96 /** 97 * Called when this tile moves into a listening state. 98 * <p/> 99 * When this tile is in a listening state it is expected to keep the 100 * UI up to date. Any listeners or callbacks needed to keep this tile 101 * up to date should be registered here and unregistered in {@link #onStopListening()}. 102 * 103 * @see #getQsTile() 104 * @see Tile#updateTile() 105 */ 106 public void onStartListening() { 107 } 108 109 /** 110 * Called when this tile moves out of the listening state. 111 */ 112 public void onStopListening() { 113 } 114 115 /** 116 * Called when the user clicks on this tile. 117 */ 118 public void onClick() { 119 } 120 121 /** 122 * Used to show a dialog. 123 * 124 * This will collapse the Quick Settings panel and show the dialog. 125 * 126 * @param dialog Dialog to show. 127 */ 128 public final void showDialog(Dialog dialog) { 129 dialog.getWindow().getAttributes().token = mToken; 130 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_QS_DIALOG); 131 dialog.show(); 132 getQsTile().onShowDialog(); 133 } 134 135 /** 136 * Gets the {@link Tile} for this service. 137 * <p/> 138 * This tile may be used to get or set the current state for this 139 * tile. This tile is only valid for updates between {@link #onStartListening()} 140 * and {@link #onStopListening()}. 141 */ 142 public final Tile getQsTile() { 143 return mTile; 144 } 145 146 @Override 147 public IBinder onBind(Intent intent) { 148 return new IQSTileService.Stub() { 149 @Override 150 public void setQSTile(Tile tile) throws RemoteException { 151 mHandler.obtainMessage(H.MSG_SET_TILE, tile).sendToTarget(); 152 } 153 154 @Override 155 public void onTileRemoved() throws RemoteException { 156 mHandler.sendEmptyMessage(H.MSG_TILE_REMOVED); 157 } 158 159 @Override 160 public void onTileAdded() throws RemoteException { 161 mHandler.sendEmptyMessage(H.MSG_TILE_ADDED); 162 } 163 164 @Override 165 public void onStopListening() throws RemoteException { 166 mHandler.sendEmptyMessage(H.MSG_STOP_LISTENING); 167 } 168 169 @Override 170 public void onStartListening() throws RemoteException { 171 mHandler.sendEmptyMessage(H.MSG_START_LISTENING); 172 } 173 174 @Override 175 public void onClick(IBinder wtoken) throws RemoteException { 176 mHandler.obtainMessage(H.MSG_TILE_CLICKED, wtoken).sendToTarget(); 177 } 178 }; 179 } 180 181 private class H extends Handler { 182 private static final int MSG_SET_TILE = 1; 183 private static final int MSG_START_LISTENING = 2; 184 private static final int MSG_STOP_LISTENING = 3; 185 private static final int MSG_TILE_ADDED = 4; 186 private static final int MSG_TILE_REMOVED = 5; 187 private static final int MSG_TILE_CLICKED = 6; 188 189 public H(Looper looper) { 190 super(looper); 191 } 192 193 @Override 194 public void handleMessage(Message msg) { 195 switch (msg.what) { 196 case MSG_SET_TILE: 197 mTile = (Tile) msg.obj; 198 break; 199 case MSG_TILE_ADDED: 200 TileService.this.onTileRemoved(); 201 break; 202 case MSG_TILE_REMOVED: 203 TileService.this.onTileAdded(); 204 break; 205 case MSG_STOP_LISTENING: 206 if (mListening) { 207 mListening = false; 208 TileService.this.onStopListening(); 209 } 210 break; 211 case MSG_START_LISTENING: 212 if (!mListening) { 213 mListening = true; 214 TileService.this.onStartListening(); 215 } 216 break; 217 case MSG_TILE_CLICKED: 218 mToken = (IBinder) msg.obj; 219 TileService.this.onClick(); 220 break; 221 } 222 } 223 } 224} 225