Быстрые настройки — это плитки, отображаемые на панели быстрых настроек и представляющие действия, которые пользователи могут использовать для быстрого выполнения повторяющихся задач. Ваше приложение может предоставить пользователям пользовательскую плитку через класс TileService
и использовать объект Tile
для отслеживания состояния плитки. Например, вы можете создать плитку, которая позволит пользователям включать или отключать VPN, предоставляемую вашим приложением.
Решите, когда создавать плитку
Мы рекомендуем создавать плитки для определенных функций, к которым, как вы ожидаете, пользователи будут часто обращаться или к которым нужен быстрый доступ (или и то, и другое). Наиболее эффективными плитками являются те, которые соответствуют обоим этим качествам, обеспечивая быстрый доступ к часто выполняемым действиям.
Например, вы можете создать плитку для фитнес-приложения, которая позволит пользователям быстро начать тренировку. Однако мы не рекомендуем создавать плитку для того же приложения, которая позволит пользователям просматривать всю историю своих тренировок.
Чтобы улучшить видимость вашей плитки и упростить ее использование, мы рекомендуем избегать определенных действий:
Избегайте использования плиток для запуска приложения. Вместо этого используйте ярлык приложения или стандартную панель запуска.
Избегайте использования плиток для одноразовых действий пользователя. Вместо этого используйте ярлык приложения или уведомление .
Избегайте создания слишком большого количества плиток. Мы рекомендуем максимум два на одно приложение. Вместо этого используйте ярлык приложения.
Избегайте использования плиток, которые отображают информацию, но не являются интерактивными для пользователей. Вместо этого используйте уведомление или виджет .
Создайте свою плитку
Чтобы создать плитку, вам необходимо сначала создать соответствующий значок плитки, а затем создать и объявить свой TileService
в файле манифеста вашего приложения.
Пример быстрых настроек представляет собой пример создания плитки и управления ею.
Создайте свой собственный значок
Вам потребуется предоставить собственный значок, который будет отображаться на плитке на панели быстрых настроек. (Вы добавите этот значок при объявлении TileService
, описанном в следующем разделе.) Значок должен быть сплошным белым с прозрачным фоном, размером 24 x 24dp и иметь форму VectorDrawable
.
Создайте значок, который визуально намекает на назначение вашей плитки. Это помогает пользователям легко определить, соответствует ли ваша плитка их потребностям. Например, вы можете создать значок секундомера для плитки фитнес-приложения, позволяющего пользователям начать тренировку.
Создайте и объявите свой TileService.
Создайте для своей плитки сервис, расширяющий класс TileService
.
Котлин
class MyQSTileService: TileService() { // Called when the user adds your tile. override fun onTileAdded() { super.onTileAdded() } // Called when your app can update your tile. override fun onStartListening() { super.onStartListening() } // Called when your app can no longer update your tile. override fun onStopListening() { super.onStopListening() } // Called when the user taps on your tile in an active or inactive state. override fun onClick() { super.onClick() } // Called when the user removes your tile. override fun onTileRemoved() { super.onTileRemoved() } }
Ява
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(); } }
Объявите свой TileService
в файле манифеста вашего приложения. Добавьте имя и метку вашего TileService
, собственный значок, созданный вами в предыдущем разделе, и соответствующее разрешение.
<service
android:name=".MyQSTileService"
android:exported="true"
android:label="@string/my_default_tile_label" // 18-character limit.
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>
Управляйте своим TileService
После того как вы создали и объявили свой TileService
в манифесте приложения, вам необходимо управлять его состоянием.
TileService
— это привязанный сервис . Ваш TileService
привязывается по запросу вашего приложения или если системе необходимо взаимодействовать с ним. Типичный жизненный цикл привязанного сервиса содержит следующие четыре метода обратного вызова: onCreate()
, onBind()
, onUnbind()
и onDestroy()
. Эти методы вызываются системой каждый раз, когда служба переходит в новую фазу жизненного цикла.
Обзор жизненного цикла TileService
Помимо обратных вызовов, управляющих жизненным циклом привязанного сервиса, необходимо реализовать другие методы, специфичные для жизненного цикла TileService
. Эти методы можно вызывать вне onCreate()
и onDestroy()
поскольку методы жизненного цикла Service
и методы жизненного цикла TileService
вызываются в двух отдельных асинхронных потоках.
Жизненный цикл TileService
содержит следующие методы, которые вызываются системой каждый раз, когда ваш TileService
переходит в новую фазу жизненного цикла:
onTileAdded()
: этот метод вызывается только тогда, когда пользователь добавляет плитку в первый раз, а также если пользователь удаляет и добавляет плитку снова. Это лучшее время для однократной инициализации. Однако это может не удовлетворить всю необходимую инициализацию.onStartListening()
иonStopListening()
: эти методы вызываются всякий раз, когда ваше приложение обновляет плитку, и вызываются часто.TileService
остается связанным междуonStartListening()
иonStopListening()
, что позволяет вашему приложению изменять плитку и отправлять обновления.onTileRemoved()
: этот метод вызывается, только если пользователь удаляет вашу плитку.
Выберите режим прослушивания
Ваш TileService
прослушивает в активном или неактивном режиме. Мы рекомендуем использовать активный режим, который вам необходимо объявить в манифесте приложения. В противном случае TileService
является стандартным режимом и его не нужно объявлять.
Не думайте, что ваш TileService
будет существовать вне пары методов onStartListening()
и onStopListening()
.
Активный режим (рекомендуется)
Используйте активный режим для TileService
, который прослушивает и отслеживает свое состояние в своем собственном процессе. TileService
в активном режиме привязан к onTileAdded()
, onTileRemoved()
, событиям касания и по запросу процесса приложения.
Мы рекомендуем активный режим, если ваш TileService
уведомляется о том, что состояние вашей плитки должно быть обновлено собственным процессом. Активные плитки ограничивают нагрузку на систему, поскольку их не нужно привязывать каждый раз, когда панель быстрых настроек становится видимой пользователю.
Статический метод TileService.requestListeningState()
можно вызвать для запроса начала состояния прослушивания и получения обратного вызова onStartListening()
.
Вы можете объявить активный режим, добавив META_DATA_ACTIVE_TILE
в файл манифеста вашего приложения.
<service ...>
<meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="true" />
...
</service>
Неактивный режим
Неактивный режим является стандартным режимом. TileService
находится в неактивном режиме, если она привязывается всякий раз, когда ваша плитка видна пользователю. Это означает, что ваш TileService
может быть создан и связан снова вне его контроля. Он также может быть отвязан и уничтожен, когда пользователь не просматривает плитку.
Ваше приложение получает обратный вызов onStartListening()
после того, как пользователь открывает панель быстрых настроек. Вы можете обновлять свой объект Tile
столько раз, сколько захотите, между onStartListening()
и onStopListening()
.
Вам не нужно объявлять неактивный режим — просто не добавляйте META_DATA_ACTIVE_TILE
в файл манифеста вашего приложения.
Обзор состояний плитки
После того как пользователь добавляет вашу плитку, она всегда находится в одном из следующих состояний.
STATE_ACTIVE
: указывает на включенное или включенное состояние. В этом состоянии пользователь может взаимодействовать с вашей плиткой.Например, для плитки фитнес-приложения, которая позволяет пользователям инициировать сеанс тренировки по времени,
STATE_ACTIVE
будет означать, что пользователь инициировал сеанс тренировки и таймер работает.STATE_INACTIVE
: указывает на выключенное или приостановленное состояние. В этом состоянии пользователь может взаимодействовать с вашей плиткой.Если снова использовать пример плитки фитнес-приложения, плитка в
STATE_INACTIVE
будет означать, что пользователь не инициировал сеанс тренировки, но может сделать это, если захочет.STATE_UNAVAILABLE
: указывает на временное недоступное состояние. В этом состоянии пользователь не может взаимодействовать с вашей плиткой.Например, плитка в
STATE_UNAVAILABLE
означает, что в данный момент плитка по какой-то причине недоступна пользователю.
Система устанавливает только начальное состояние вашего объекта Tile
. Вы устанавливаете состояние объекта Tile
на протяжении всего его жизненного цикла.
Система может изменить цвет значка и фона плитки, чтобы отразить состояние вашего объекта Tile
. Объекты Tile
, для которых установлено значение STATE_ACTIVE
являются самыми темными, а STATE_INACTIVE
и STATE_UNAVAILABLE
становятся светлее. Точный оттенок зависит от производителя и версии.
Обновите плитку
Вы можете обновить свою плитку, как только получите обратный вызов onStartListening()
. В зависимости от режима плитки ваша плитка может быть обновлена хотя бы один раз, пока не будет получен обратный вызов onStopListening()
.
В активном режиме вы можете обновить свою плитку ровно один раз, прежде чем получите обратный вызов onStopListening()
. В неактивном режиме вы можете обновлять плитку столько раз, сколько захотите, между onStartListening()
и onStopListening()
.
Вы можете получить объект Tile
, вызвав getQsTile()
. Чтобы обновить определенные поля вашего объекта Tile
, вызовите следующие методы:
Вы должны вызвать updateTile()
, чтобы обновить плитку, как только вы закончите установку полей объекта Tile
в правильные значения. Это заставит систему проанализировать обновленные данные плитки и обновить пользовательский интерфейс.
Котлин
data class StateModel(val enabled: Boolean, val label: String, val icon: Icon) override fun onStartListening() { super.onStartListening() val state = getStateFromService() qsTile.label = state.label qsTile.contentDescription = tile.label qsTile.state = if (state.enabled) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE qsTile.icon = state.icon qsTile.updateTile() }
Ява
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(); }
Ручки кранов
Пользователи могут нажать на вашу плитку, чтобы вызвать действие, если ваша плитка находится в состоянии STATE_ACTIVE
или STATE_INACTIVE
. Затем система вызывает обратный вызов onClick()
вашего приложения.
Как только ваше приложение получит обратный вызов onClick()
, оно может запустить диалог или действие, запустить фоновую работу или изменить состояние вашей плитки.
Котлин
var clicks = 0 override fun onClick() { super.onClick() counter++ qsTile.state = if (counter % 2 == 0) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE qsTile.label = "Clicked $counter times" qsTile.contentDescription = qsTile.label qsTile.updateTile() }
Ява
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()
сворачивает панель быстрых настроек и отображает диалоговое окно. Используйте диалоговое окно, чтобы добавить контекст к вашему действию, если оно требует дополнительных данных или согласия пользователя.
Запустить мероприятие
startActivityAndCollapse()
запускает действие при сворачивании панели. Действия полезны, если нужно отобразить более подробную информацию, чем в диалоговом окне, или если ваше действие очень интерактивно.
Если ваше приложение требует значительного взаимодействия с пользователем, приложение должно запускать действие только в крайнем случае. Вместо этого рассмотрите возможность использования диалогового окна или переключателя.
Длительное нажатие на плитку открывает экран информации о приложении для пользователя. Чтобы переопределить это поведение и вместо этого запустить действие для настройки предпочтений, добавьте <intent-filter>
к одному из ваших действий с помощью ACTION_QS_TILE_PREFERENCES
.
Начиная с Android API 28, PendingIntent
должен иметь Intent.FLAG_ACTIVITY_NEW_TASK
:
if (Build.VERSION.SDK_INT >= 28) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
Альтернативно вы можете добавить флаг в AndroidManifest.xml
в определенном разделе Activity
.
Отметьте свою плитку как переключаемую
Мы рекомендуем пометить плитку как переключаемую, если она в основном работает как переключатель с двумя состояниями (что является наиболее распространенным поведением плиток). Это помогает предоставить информацию о поведении плитки операционной системе и улучшить общую доступность.
Установите для метаданных TOGGLEABLE_TILE
значение true
чтобы пометить плитку как переключаемую.
<service ...>
<meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true" />
</service>
Выполняйте только безопасные действия на надежно заблокированных устройствах.
Ваша плитка может отображаться поверх экрана блокировки на заблокированных устройствах. Если плитка содержит конфиденциальную информацию, проверьте значение isSecure()
чтобы определить, находится ли устройство в безопасном состоянии, и ваш TileService
должен соответствующим образом изменить свое поведение.
Если действие плитки безопасно выполнять во время блокировки, используйте startActivity()
чтобы запустить действие поверх экрана блокировки.
Если действие плитки небезопасно, используйте unlockAndRun()
, чтобы предложить пользователю разблокировать свое устройство. В случае успеха система выполняет объект Runnable
, который вы передаете в этот метод.
Предложите пользователю добавить вашу плитку
Чтобы вручную добавить плитку, пользователи должны выполнить несколько шагов:
- Проведите пальцем вниз, чтобы открыть панель быстрых настроек.
- Нажмите кнопку редактирования.
- Пролистывайте все плитки на их устройстве, пока они не найдут вашу плитку.
- Удерживая плитку, перетащите ее в список активных плиток.
Пользователь также может переместить или удалить свою плитку в любой момент.
Начиная с Android 13, вы можете использовать метод requestAddTileService()
чтобы пользователям было намного проще добавлять плитку на устройство. Этот метод предлагает пользователям быстро добавить вашу плитку прямо на панель быстрых настроек. Приглашение включает имя приложения, предоставленную метку и значок.
public void requestAddTileService (
ComponentName tileServiceComponentName,
CharSequence tileLabel,
Icon icon,
Executor resultExecutor,
Consumer<Integer> resultCallback
)
Обратный вызов содержит информацию о том, была ли плитка добавлена или нет, была ли она там уже или произошла ли какая-либо ошибка.
Действуйте по своему усмотрению, решая, когда и как часто предлагать пользователям. Мы рекомендуем вызывать requestAddTileService()
только в контексте — например, когда пользователь впервые взаимодействует с функцией, которую поддерживает ваша плитка.
Система может остановить обработку запросов для данного ComponentName
, если пользователь уже достаточно раз отклонил его. Пользователь определяется на основе Context
, используемого для получения этой службы — он должен соответствовать текущему пользователю.