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