jcarnide jcarnide - 1 year ago 115
Android Question

Custom Quick Settings Tile Remains in Unavailable State when Bound to Activity

I'm trying to add a custom quick settings tile for my application. I've followed the sample code/documentation from Google but I'm running into some issues. After searching for some time I couldn't find any solutions.

When I run my app, the tile is visible in the quick settings tray, but it remains in an unavailable state.

I need a two-way flow of communication with the tile, i.e., when the user selects the tile, the app responds and when the user does a certain action within the app, the tile UI is toggled.

The problem seems to come from attempting to bind my custom

class to my
-- whenever I bind it is when the tile goes into a consistently unavailable state. I can't seem to figure out why though because it's being bound successfully. If I don't bind it (i.e. just have the one way communication of the tile commanding the app), the tile is active and the app responds to selecting it.

Ultimately I do the binding to attain a reference to my custom
class to be able to call it's method
. I'm not looking to use a singleton or static member variable as a solution to getting a reference to my service.

Here's what I have in my

<action android:name="android.service.quicksettings.action.QS_TILE" />

Here's my

public class ConnectionQuickSettingsService extends TileService {
private static final String TAG = "ConnectionQuickSettingsService";
private final IBinder mBinder = new LocalBinder();

public class LocalBinder extends Binder {
ConnectionQuickSettingsService getService() {
return ConnectionQuickSettingsService.this;

public IBinder onBind(Intent i) {
return mBinder;

public void onTileAdded() {
L.d(TAG, "onTileAdded()");

public void onStartListening() {
L.d(TAG, "onStartListening()");

public void onClick() {
L.d(TAG, "Quick Settings tile selected");

private void toggleInAppSwitch() {

public void toggleTileUI() {
Tile tile = this.getQsTile();


and lastly (the relevant parts of) my

protected void onStart() {
Intent i = new Intent(this, ConnectionQuickSettingsService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);

protected void onStop() {
if (mBound) {
mBound = false;

private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
ConnectionQuickSettingsService.LocalBinder binder = (ConnectionQuickSettingsService.LocalBinder) service;
mQSService = binder.getService();
mBound = true;
L.d(TAG, "Bound to QS service successfully");

public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
L.d(TAG, "Disconnected from QS service");

public void onOnOff(){
L.d(TAG, "On/Off switch toggled");
if (mBound) {

Any input would be greatly appreciated, thanks!

Answer Source

Part of your problem is that you are overriding onBind(), which clobbers the TileService implementation of onBind(), preventing Android from working with your ConnectionQuickSettingsService. I would expect that there would be error messages in LogCat from a system process complaining about this.

The other part of your problem is that you assume that getQsTile() works at arbitrary points in time. It doesn't.

I recommend finding some other interaction pattern with your tile, such as using META_DATA_ACTIVE_TILE and requestListeningState(), and getting rid of your Binder and onBind() method.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download