Android - Quick Settings Quick Settings Tile (create custom quick settings tiles)
Introduction
Quick Settings are tiles that appear in the Quick Settings pane and represent actions that users can tap to quickly complete recurring tasks. Your application can provide users with custom tiles through the TileService class, and use the tile object to track the state of the tile. For example, you could create a header that lets users turn on or off the VPN offered by your app.
Scenarios for Quick Settings tiles
We recommend creating tiles for specific features that users access frequently or need quick access to (or both). The most effective textures are those that match both of these qualities, giving players quick access to frequently performed actions.
For example, you could create a title for a fitness app that allows users to quickly start a workout session. However, we do not recommend creating a header for the same application that allows users to view their entire workout history.
To help improve the discoverability and ease of use of tiles, we recommend avoiding the following practices:
- Avoid using tiles to launch applications. Use application shortcuts or standard launchers.
- Avoid using tiles for one-off user actions. Use app shortcuts or notifications instead.
- Avoid creating too many tiles. A maximum of two per application is recommended.
- Avoid tiles that display information but cannot interact with the user. Use notifications or widgets instead.
Create tiles
To create a tile, you need to first create an appropriate tile icon, then create and declare your TileService in your application's manifest file.
Note: Creating a tile service for your app does not add it to the user's quick settings panel. Only after the user adds a tile, your tile service will act as the interface of the tile.
Create custom icons
A custom icon needs to be provided, which is displayed on the tile in the Quick Settings panel (this will be added when declaring the TileService). Icons must be a solid white with a transparent background, be 24 x 24dp in size, and VectorDrawable
be presented as a .
Create an icon that visually hints at the purpose of your title. This helps users easily identify whether your tile fits their needs. For example, you could create a stopwatch icon for the title of a fitness app that allows users to start exercising.
Create and declare your tile service
TileService
Create a service that extends the class for tiles .
public class MyQSTileService extends TileService {
// Called when the user adds your tile.
@Override
public void onTileAdded() {
super.onTileAdded();
}
// Called when your app can update your tile.
@Override
public void onStartListening() {
super.onStartListening();
}
// Called when your app can no longer update your tile.
@Override
public void onStopListening() {
super.onStopListening();
}
// Called when the user taps on your tile in an active or inactive state.
@Override
public void onClick() {
super.onClick();
}
// Called when the user removes your tile.
@Override
public void onTileRemoved() {
super.onTileRemoved();
}
}
manifest
Declare yours in your app's files TileService
. Add your TileService
name and tags, the custom icon created in the previous section, and appropriate permissions.
<service
android:name=".MyQSTileService"
android:label="@string/my_default_tile_label"
android:icon="@drawable/my_default_icon_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
Manage your tile service
Once you have created and declared your TileService in the application manifest, you must manage its state.
TileService
is a bound service. TileService
Yours is bound when your application requests it or when the system needs to communicate with it . A typical bound service life cycle contains the following four callback methods: onCreate()
, onBind()
, onUnbind()
and onDestroy()
. These methods are called each time the service enters a new lifecycle phase.
Note: yours
TileService
will still go through the typical service lifecycle. However,TileService
it differs from most other bound services in that it includes specificTileService
lifecycle methods that the application must respond to.
TileService life cycle
In addition to the callbacks that control the lifecycle of the bound service, you must implement other methods specific to the lifecycle of the tile service. These methods can be called outside of onCreate()
and onDestroy()
because Service
lifecycle methods and TileService
lifecycle methods are called in two separate asynchronous threads.
TileService
The lifecycle contains the following methods, TileService
which are called by the system every time your object enters a new lifecycle phase:
onTileAdded()
: This method is only called when the user adds your tile for the first time, and if the user deletes and adds your tile again. This is the perfect time to do a one-time initialization. However, this may not satisfy all required initializations.
Description: The tile has already been created and
onTileAdded()
will not be called. For example, if a tile was added and not removed before the device was powered off, it will not be called when the device is restarted or powered uponTileAdded()
.
onStartListening()
andonstoppllistening()
: These methods are called when the application updates the tile, and are called frequently.TileService
Still bound betweenonStartListening()
andonstoppllistening()
, allowing your app to modify tiles and push updates.onTileRemoved()
: This method is only called when the user deletes your sticker.
Explanation: These phases may not occur consecutively.
onTileAdded()
Probably only called once when the user adds a tile to their Quick Settings panel.onStartListening()
andonstoppllistening()
can be called multiple times during the lifecycle of the tile service.onTileRemoved()
Will never be called if the user hasn't deleted your texture from their quick settings panel .
Select monitor mode
Your listening TileService
in active mode or non-active mode . It is recommended to use the activity pattern, which you need to declare in the application manifest. Otherwise, TileService
it is standard mode and no declaration is required.
Active mode (recommended)
For TileService
use active mode
, it listens and monitors its status in its own process. non-active mode
In the mode, TileService
it is bound to the onTileAdded()
, onTileRemoved()
, tap events and when requested by the application process.
We recommend using active mode if your tile service is notified when your tile state needs to be updated by its own process. Live tiles limit the strain on the system because they don't have to be bound every time the quick settings panel becomes visible to the user.
A static TileService.requestListeningState()
method can be called to request the start of the listening state, and receive onStartListening()
a callback for the object.
You can declare active mode by adding in the application's manifest
file .META_DATA_ACTIVE_TILE
<service ...>
<meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="true" />
...
</service>
Non-active mode
The non-active mode is the standard mode. When your tile is visible to the user, it is in non-active mode if it is bound to a tile service. This means yours TileService
may be created and bound again under circumstances beyond its control. It is also possible to unbind and destroy the tile when the user is not viewing it.
The callback your app receives after the user opens their quick settings panel onStartListening()
. You can update the Tile object as much as you want between onStartListening()
and .onstoppllistening()
Note: If you use non-active mode instead of active mode, yours
TileService
may be bound every time a user opens their quick settings panel.
You don't need to declare non-active mode, just don't META_DATA_ACTIVE_TILE
add it to your application's manifest
files.
Tile status
After a user adds your tile, it always exists in one of the following states.
STATE_ACTIVE
: Enabled or Enabled state. In this state, the user can interact with the tile.
For example, for a fitness app title that allows the user to start a timed workout session,STATE_ACTIVE
it would mean that the user has already started the workout session and the timer is running.STATE_INACTIVE
: Closed or paused state. In this state, the user can interact with the tile.
Using the fitness app tile example again,STATE_INACTIVE
the tile in means that the user hasn't started a workout session yet, but could do so if they wanted to.STATE_UNAVAILABLE
: Temporarily unavailable. In this state, the user cannot interact with the tile.
For example,STATE_UNAVAILABLE
a tile in means that for some reason, the tile is currently unavailable to the user.
Description: Will
STATE_UNAVAILABLE
be used for tiles that are currently unavailable but may become available later.COMPONENT_ENABLED_STATE_DISABLED
Will be passed to if the user can no longer use the componentsetComponentEnabledSetting()
.
The system only sets the initial state of the Tile object. Sets the state of the Tile object for the remainder of its lifetime.
Update tiles
You can onStartListening()
update your tiles after receiving the callback. Depending on the mode of the tile, the tile may be updated at least once until a callback is received onStoppListening()
.
In mode, you can update your tile once before active
receiving the callback. onStoppListening()
In non-active
mode, you can update your tiles as much as you like between and onStartListening()
.onStoppListening()
You can getQsTile()
retrieve a Tile object by calling To update a specific field of a Tile object, call the following method:
setContentDescription()
setIcon()
setLabel()
setState()
setStateDescription()
setSubtitle()
Description: The icons and labels set in your app's manifest file are the default values displayed on tiles in the Quick Settings panel. However, the setIcon() and setLabel() methods can be called to set fields to new values when the tile is updated.
Once a tile object's field has been set to a new value, it must be called updateTile()
to update the tile. This will cause the system to parse the updated tile data and update the UI.
public class StateModel {
final boolean enabled;
final String label;
final Icon icon;
public StateModel(boolean e, String l, Icon i) {
enabled = e;
label = l;
icon = i;
}
}
@Override
public void onStartListening() {
super.onStartListening();
StateModel state = getStateFromService();
Tile tile = getQsTile();
tile.setLabel(state.label);
tile.setContentDescription(state.label);
tile.setState(state.enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.setIcon(state.icon);
tile.updateTile();
}
Handle the tap event
If your sticker is in the STATE_ACTIVE
or STATE_INACTIVE
state, the user can click on your sticker to trigger an action. The system then calls the application's onClick()
callback.
Once your app receives onClick()
the callback, it can start a dialog or activity, trigger background work, or change the state of your tiles.
int clicks = 0;
@Override
public void onClick() {
super.onClick();
counter++;
Tile tile = getQsTile();
tile.setState((counter % 2 == 0) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.setLabel("Clicked " + counter + " times");
tile.setContentDescription(tile.getLabel());
tile.updateTile();
}
start dialog
showDialog()
Collapses the Quick Settings panel and displays a dialog. If additional input or user consent is required, dialogs can be used to add context to the action.
Description:
isLocked()
Checks if the user's lock screen is displayed. WhenisLocked()
returningtrue
,showDialog()
a visible dialog is not shown because it loads under the lock screen.
Start Activity
startActivityAndCollapse()
Start one when the panel is collapsed Activity
. Activity
Useful if you want to display more detailed information than a dialog box, or if your operations are highly interactive .
If your app requires a lot of user interaction, the app should launch one Activity
as a last resort. Instead, consider using dialogs or switches.
Long-pressing a tile will prompt the user to enter the application information interface. To override this behavior and start one Activity
to set preferences, use ACTION_QS_TILE_PREFERENCES
Add to one of the activities <intent-filter>
.
Mark tiles as toggleable
If your texture is mainly used as a switch between two states (this is the most common behavior of textures), we recommend that you mark it as toggleable. This helps provide information to the operating system about the tile's behavior and improves general accessibility.
Set TOGGLEABLE_TILE
metadata true
to mark your tile as toggleable.
<service ...>
<meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true" />
</service>
Security operations can only be performed on security-locked devices
On locked devices, tiles may appear at the top of the lock screen. If the tile contains sensitive information, check isSecure()
the value of s to determine if the device is in a secure state, and yours TileService
should change its behavior accordingly.
If it is safe to perform tiling operations while locked, use startActivity()
Launch an activity on top of the lock screen.
unlockAndRun()
Use to prompt the user to unlock their device if the tile operation is not secure . If successful, the system executes Runnable
the object passed into this method.
Prompt the user to add a tile
To manually add tiles, the user must follow a few steps:
- Swipe down to open the quick settings panel.
- Click the Edit button.
- Scroll through all the stickers on your device until you find yours.
- Press and hold your tile, and drag it to the live tile list.
Users can also move or delete your tiles at any time. Starting in Android 13, you can use requestAddTileService()
methods to make it easier for users to add your tiles to the device. This method prompts the user to request that your tile be quickly added directly to their Quick Settings panel. The prompt includes the application name, provided label, and icon.
public void requestAddTileService (
ComponentName tileServiceComponentName,
CharSequence tileLabel,
Icon icon,
Executor resultExecutor,
Consumer<Integer> resultCallback
)
The callback contains information about whether it was added, not added, already exists, or if any errors occurred. Use your discretion when deciding when and how often to prompt the user. We recommend only calling this in context requestAddTileService()
- such as when the user first interacts with the feature your tile facilitates.
Description: We recommend calling
requestAddTileService()
to increase the discoverability of your tiles and reduce the burden on users to add your tiles to the quick settings panel.