Android——快速设置Quick Settings Tile(创建自定义快速设置磁贴)
- 简介
- 快速设置磁贴的使用场景
- 创建磁贴
- 创建自定义图标
- 创建并声明你的tile服务
- 管理你的tile服务
- TileService生命周期
- 选择监听模式
- Active mode (推荐)
- Non-active mode
- Tile状态
- 更新Tile
- 处理tap事件
- 启动对话框
- 启动Activity
- 将tile标记为可切换的
- 只能在安全锁定的设备上执行安全操作
- 提示用户添加tile
简介
快速设置是显示在快速设置面板中的磁贴,表示操作,用户可以点击这些操作来快速完成重复出现的任务。你的应用可以通过TileService类为用户提供自定义的tile,并使用tile对象来跟踪tile的状态。例如,你可以创建一个标题,让用户打开或关闭应用程序提供的VPN。
快速设置磁贴的使用场景
我们建议为用户经常访问或需要快速访问(或两者兼而有之)的特定功能创建磁贴。最有效的贴图是那些同时符合这两种品质的贴图,让玩家能够快速访问频繁执行的操作。
例如,可以为健身应用程序创建一个标题,允许用户快速开始锻炼会话。然而,我们不建议为同一个应用程序创建一个允许用户查看其整个锻炼历史的标题。
为了帮助提高tile的可发现性和易用性,我们建议避免以下做法:
- 避免使用磁贴来启动应用程序。使用应用程序快捷方式或标准启动器。
- 避免将磁贴用于一次性用户操作。使用应用程序快捷方式或通知代替。
- 避免创建太多的磁贴。建议每个应用最多使用两个。
- 避免使用显示信息但不能与用户交互的磁贴。使用通知或小部件代替。
创建磁贴
要创建一个tile,你需要首先创建一个合适的tile图标,然后在应用的manifest文件中创建并声明你的TileService。
说明:为你的应用创建一个tile服务并不会将它添加到用户的快速设置面板中。只有在用户添加tile之后,你的tile服务才会作为tile的接口。
创建自定义图标
需要提供一个自定义图标,该图标显示在Quick Settings面板中的tile上(将在声明TileService时添加此图标)。图标必须是纯白色的透明背景,尺寸为24 x 24dp,并以VectorDrawable
的形式呈现。
创建一个图标,在视觉上暗示你的标题的目的。这可以帮助用户轻松识别你的tile是否符合他们的需求。例如,你可以为允许用户开始锻炼的健身应用程序的标题创建一个秒表图标。
创建并声明你的tile服务
为tile创建一个扩展TileService
类的服务。
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
文件中声明你的TileService
。添加你的TileService
的名称和标签、在上一节中创建的自定义图标以及适当的权限。
<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>
管理你的tile服务
一旦你在应用程序清单中创建并声明了你的TileService,你就必须管理它的状态。
TileService
是一个绑定服务。当你的应用程序请求或者系统需要与它通信时,你的TileService
被绑定。一个典型的绑定服务生命周期包含以下四个回调方法:onCreate()
、onBind()
、onUnbind()
和onDestroy()
。每次服务进入新的生命周期阶段时,系统都会调用这些方法。
说明:你的
TileService
仍然会经历典型的服务生命周期。然而,TileService
与大多数其他绑定服务不同,因为它包含了应用程序必须响应的特定于TileService
的生命周期方法。
TileService生命周期
除了控制绑定服务生命周期的回调之外,你还必须实现其他特定于tile服务生命周期的方法。这些方法可以在onCreate()
和onDestroy()
之外调用,因为Service
生命周期方法和TileService
生命周期方法是在两个独立的异步线程中调用的。
TileService
生命周期包含以下方法,每次你的TileService
进入一个新的生命周期阶段时,系统都会调用这些方法:
onTileAdded()
:此方法仅在用户第一次添加您的tile时调用,以及如果用户删除并再次添加您的tile时调用。这是进行一次性初始化的最佳时机。然而,这可能不能满足所有需要的初始化。
说明:tile已经被创建,
onTileAdded()
不会被调用。例如,如果在设备关闭电源之前添加了tile并且没有删除,则在设备重新启动或上电时不会调用onTileAdded()
。
onStartListening()
和onstoppllistening()
:这些方法在应用程序更新tile时被调用,并且经常被调用。TileService
仍然绑定在onStartListening()
和onstoppllistening()
之间,允许你的应用修改tile和推送更新。onTileRemoved()
:这个方法只在用户删除你的贴图时被调用。
说明:这些阶段可能不是连续发生的。
onTileAdded()
可能只在用户将tile添加到他们的Quick Settings面板时调用一次。onStartListening()
和onstoppllistening()
可以在tile服务的生命周期中被调用多次。如果用户没有从他们的快速设置面板中删除你的贴图,onTileRemoved()
将永远不会被调用。
选择监听模式
你的TileService
以active mode或non-active mode侦听。建议使用活动模式,你需要在应用程序清单中声明。否则,TileService
就是标准模式,不需要声明。
Active mode (推荐)
为TileService
使用active mode
,它在自己的进程中侦听和监视其状态。non-active mode
模式下的TileService
被绑定到onTileAdded()
、onTileRemoved()
、tap事件以及被应用进程请求时。
如果你的tile服务在你的tile状态需要被它自己的进程更新时收到通知,我们推荐使用active模式。活动磁贴限制了系统的压力,因为它们不必在每次快速设置面板对用户可见时都被绑定。
可以调用静态TileService.requestListeningState()
方法来请求侦听状态的开始,并接收对onStartListening()
的回调。
你可以通过在应用程序的manifest
文件中添加META_DATA_ACTIVE_TILE
来声明active模式。
<service ...>
<meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="true" />
...
</service>
Non-active mode
non-active模式为标准模式。当你的tile对用户可见时,如果绑定了tile服务,那么它就处于non-active模式。这意味着你的TileService
可能会在其无法控制的情况下再次创建和绑定。当用户不查看tile时,也可以解除绑定并销毁它。
你的应用程序在用户打开他们的快速设置面板后接收到onStartListening()
的回调。你可以在onStartListening()
和onstoppllistening()
之间尽可能多地更新Tile对象。
说明:如果你使用non-active模式而不是active模式,你的
TileService
可能会在每次用户打开他们的快速设置面板时被绑定。
你不需要声明non-active模式,只需不将META_DATA_ACTIVE_TILE
添加到应用程序的manifest
文件中。
Tile状态
用户添加你的tile后,它总是以以下状态之一存在。
STATE_ACTIVE
:开启或启用状态。在这种状态下,用户可以与tile进行交互。
例如,对于允许用户启动定时锻炼会话的健身应用程序标题,STATE_ACTIVE
将意味着用户已经启动了锻炼会话并且计时器正在运行。STATE_INACTIVE
:关闭或暂停状态。在这种状态下,用户可以与tile进行交互。
再次使用健身应用程序磁贴的例子,STATE_INACTIVE
中的磁贴意味着用户还没有启动锻炼会话,但如果他们想这样做的话,可以这样做。STATE_UNAVAILABLE
:暂时不可用状态。在此状态下,用户无法与磁贴进行交互。
例如,STATE_UNAVAILABLE
中的贴片意味着由于某种原因,该贴片当前对用户不可用。
说明:将
STATE_UNAVAILABLE
用于当前不可用但稍后可能会进入可用状态的磁贴。如果用户再也无法使用该组件,则将COMPONENT_ENABLED_STATE_DISABLED
传递给setComponentEnabledSetting()
。
系统只设置Tile对象的初始状态。在Tile对象的剩余生命周期中设置其状态。
更新Tile
你可以在收到onStartListening()
的回调后更新你的tile。根据tile的模式,tile可以至少更新一次,直到接收到对onStoppListening()
的回调。
在active
模式下,可以在接收到onStoppListening()
的回调之前更新你的tile一次。在non-active
模式下,你可以在onStartListening()
和onStoppListening()
之间尽可能多地更新你的tile。
你可以通过调用getQsTile()
来检索Tile对象。要更新Tile对象的特定字段,请调用以下方法:
setContentDescription()
setIcon()
setLabel()
setState()
setStateDescription()
setSubtitle()
说明: 在你的应用程序的清单文件中设置的图标和标签是在快速设置面板的平铺上显示的默认值。但是,可以在更新tile时调用setIcon()和setLabel()方法来将字段设置为新值。
一旦将tile对象的字段设置为新的值,就必须调用updateTile()
来更新tile。这将使系统解析更新的tile数据并更新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();
}
处理tap事件
如果你的贴图处于STATE_ACTIVE
或STATE_INACTIVE
状态,用户可以点击你的贴图来触发一个动作。然后系统调用应用程序的onClick()
回调。
一旦你的应用程序接收到onClick()
的回调,它可以启动一个对话框或活动,触发后台工作,或者改变你的tile的状态。
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();
}
启动对话框
showDialog()
折叠Quick Settings面板并显示一个对话框。如果需要额外的输入或用户同意,可以使用对话框为操作添加上下文。
说明:
isLocked()
检查用户的锁屏幕是否显示。当isLocked()
返回true
时,showDialog()
不会显示一个可见的对话框,因为它在锁定屏幕下加载。
启动Activity
startActivityAndCollapse()
在折叠面板时启动一个Activity
。如果要显示比对话框更详细的信息,或者您的操作具有高度交互性,那么Activity
是有用的。
如果你的应用需要大量的用户交互,应用应该启动一个Activity
作为最后的手段。相反,可以考虑使用对话框或开关。
长按一个磁贴会提示用户进入应用信息界面。要覆盖此行为并启动一个Activity
来设置首选项,请使用ACTION_QS_TILE_PREFERENCES
向其中一个活动添加<intent-filter>
。
将tile标记为可切换的
如果你的贴图主要作为两种状态的切换(这是贴图最常见的行为),我们建议你将它标记为toggleable。这有助于向操作系统提供有关tile行为的信息,并提高总体可访问性。
将TOGGLEABLE_TILE
元数据设置为true
以将您的tile标记为可切换的。
<service ...>
<meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true" />
</service>
只能在安全锁定的设备上执行安全操作
在锁定的设备上,磁贴可能会显示在锁定屏幕的顶部。如果tile包含敏感信息,请检查isSecure()
的值以确定设备是否处于安全状态,并且你的TileService
应该相应地更改其行为。
如果在锁定时执行平铺操作是安全的,则使用startActivity()
在锁定屏幕的顶部启动一个活动。
如果平铺操作不安全,使用unlockAndRun()
来提示用户解锁他们的设备。如果成功,系统将执行传入此方法的Runnable
对象。
提示用户添加tile
要手动添加tile,用户必须遵循以下几个步骤:
- 向下滑动打开快速设置面板。
- 点击编辑按钮。
- 在设备上滚动所有的贴图,直到找到你的贴图。
- 按住你的磁贴,并将其拖到活动磁贴列表中。
用户还可以在任何时候移动或删除你的tile。从Android 13开始,你可以使用requestAddTileService()
方法来让用户更容易地将你的tile添加到设备上。此方法提示用户请求快速将你的tile直接添加到他们的Quick Settings面板中。提示符包括应用程序名称、提供的标签和图标。
public void requestAddTileService (
ComponentName tileServiceComponentName,
CharSequence tileLabel,
Icon icon,
Executor resultExecutor,
Consumer<Integer> resultCallback
)
回调包含有关是否添加、未添加、是否已经存在或是否发生任何错误的信息。在决定何时以及多长时间提示用户时,请自行决定。我们建议只在上下文中调用requestAddTileService()
——例如当用户第一次与你的tile所促进的特性交互时。
说明: 我们建议调用
requestAddTileService()
来增加你的tile的可发现性,并减少用户将你的tile添加到快速设置面板的负担。