С версии ОС Android 7.1 (API 25) Google предлагает нам новый механизм работы с приложениями — Android Shortcuts. Мы написали краткий обзор этой фичи, созданной для удобства пользователей.
Общий обзор
В переводе с английского «shortcut» — кратчайший путь, такое название хорошо отражает основное предназначение шорткатов. Они позволяют нам попасть в какую-то определенную точку приложения и выполнить конкретное действие всего за пару нажатий. Шорткаты неплохо смотрятся, например, если пользователю надо:
• выбрать заранее определенный маршрут в навигаторе;
• начать беседу с другом в мессенджере;
• продолжить игру с последней точки сохранения.
Основные компоненты
Шорткат включает в себя:
1) интент или массив интентов, которые запускают конкретное действие;
2) идентификатор или ID, определяющий именно этот шорткат;
3) короткое и длинное сообщения, отображающиеся при его показе;
4) иконка слева от текста.
Чтобы лучше разобраться в механике работы с шорткатами, рассмотрим их классификацию.
Виды шорткатов
Android предлагает 2 вида шорткатов (на самом деле их три, но об этом ниже): статические и динамические. Далее рассмотрим каждый тип шорткатов с небольшими примерами и пояснениями.
Статические шорткаты
Описание статических шорткатов содержится в xml
-файле. Они создаются один раз, их нельзя удалить, добавить и изменить без обновления приложения, но их достаточно просто создать.
shortcuts.xml
, содержащийся в res/xml/
:
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="id1"
android:enabled="true"
android:icon="@drawable/shortcut_search"
android:shortcutShortLabel="@string/shortcut_short_label"
android:shortcutLongLabel="@string/shortcut_long_label"
android:shortcutDisabledMessage="@string/disabled_message">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="com.example.myapplication"
android:targetClass="com.example.myapplication.MainActivity" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
</shortcuts>
И пара строк в AndroidManifest.xml
:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
Удалить шорткат или поменять его составляющие никак не получится, пока приложение не будет обновлено.
Статические шорткаты рекомендуется использовать для тех действий, которые точно никак не изменятся из-за пользовательских манипуляций с приложением и всегда будут доступны. Например, открыть новый поисковый запрос, перейти в настройки уведомлений, начать новую беседу. Однако использовать статический шорткат, к примеру, для того, чтобы отправлять пользователя сразу на экран авторизации — не очень хорошая идея. А что, если он уже авторизован? Тогда это действие не имеет смысла. В таких случаях нам пригодятся динамические шорткаты.
Динамические шорткаты
Их можно добавлять, удалять, изменять в режиме реального времени, то есть в зависимости от тех или иных событий. Вернемся к примеру с авторизацией: если пользователь не авторизован, то добавляем этот шорткат, как только авторизовался — удаляем.
Все взаимодействие с шорткатами программно происходит через класс ShortcutManager, доступный для 23 версии API, однако большинство его методов доступны только для 25 версии API. Операции с ними достаточно просты, но есть некоторые нюансы, которые будут подробно рассмотрены дальше.
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1")
.setShortLabel("Search")
.setLongLabel("Start new search")
.setIcon(Icon.createWithResource(context, R.drawable.shortcut_search))
.setIntent(new Intent(Intent.ACTION_VIEW,
Uri.parse("shortcutapp://search")))
.build();
shortcutManager.setDynamicShortcuts(Collections.singletonList(shortcut));
Удалять и изменять динамические шорткаты также достаточно просто:
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
shortcutManager.removeDynamicShortcuts(Arrays.asList("id1", "id2"));
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
shortcutManager.updateShortcuts(Arrays.asList(shortcut1, shortcut2));
Закрепленные шорткаты
На самом деле есть еще один вид шорткатов — это, если дословно переводить, «приколотые» или «закрепленные» (pinned) шорткаты. Выглядят они так:
Создавать такие шорткаты программным образом нельзя, как и удалять. Это может сделать только сам пользователь. Но с помощью кода их можно отключить (disableShortcuts()
). Можно закреплять как статические, так и динамические шорткаты.
IllegalArgumentException
с сообщением о том, что статические шорткаты нельзя изменять динамически.
Прежде, чем удалять динамический шорткат, убедитесь, что закрепленный тоже будет отключен, иначе это может вызвать проблемы в работе приложения.
При дизейбле любого шортката можно задать соответствующее сообщение, которое будет выведено пользователю при нажатии на него.
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
shortcutManager.disableShortcuts(Collections.singletonList(id), "Removed");
Мы ознакомились с шорткатами и основными принципами их работы в целом. Теперь можно перейти к деталям, особенностям и практическим советам.
Детали и тонкости применения
1. При добавлении шорткатов в большинстве случаев они будут отображаться от первого добавленного к последнему, первый добавленный будет ближе всех к иконке приложения. Сначала будут отображены статические, затем динамические.
getRank()
. Но самостоятельно этот ранг задать нельзя, его устанавливает ОС по своим соображениям. Пока во всех случаях, что нам встречались, этот ранг задавался в зависимости от очередности добавления. Ранг, к слову, это неотрицательное число, и чем ниже это число, тем «приоритетнее» считается шорткат, тем ближе он расположится к иконке приложения (ранг 0 — самый близкий).
2. При создании шортката необходимо установить длинное и короткое сообщения. Длинное сообщение указывается в списке, если оно не вмещается — то короткое. Google рекомендует устанавливать короткое сообщение не более 10 символов, а длинное — не более 25.
3. Несмотря на то, что можно добавить максимально пять шорткатов, Google рекомендует не добавлять более четырех. Да и в списке больше четырех шорткатов не отобразится (последний добавленный не покажется). Зачем нужен пятый шорткат — загадка, ведь на планшетах он тоже не отображается.
4. У атрибута targetPackage
статических шорткатов есть одна особенность — он может иметь только хардкод-значение. Если у Вас для разных сборок приложения используются различные суффиксы applicationId
, то при объявлении шортката указать значение targetPackage ссылкой, например, @string/shortcut_target_package
, не получится. Придется создавать файл shortcuts.xml
отдельно для каждого buildFlavour
приложения и прописывать необходимый targetPackage
вручную с нужным суффиксом applicationId
.
5. Важно, что Android сам никак не регулирует количество добавляемых шорткатов. Если вы по какой-то причине захотите добавить шестой шорткат, приложение просто упадет, выбросив IllegalArgumentException: Max number of dynamic shortcuts exceeded
. Самостоятельно следите за количеством добавляемых шорткатов.
6. Если не задать хотя бы одному интенту шортката атрибут action, то в случае динамического шортката приложение упадет при создании этого шортката, а в случае статического — шорткат просто не будет создан. Отметим, что в extras интентов шортката нельзя положить некоторые типы, например, Serializable
, допустимые типы можно увидеть в исходниках PersistableBundle.
7. Если попытаться вызвать getSystemService(ShortcutManager.class)
на устройстве ниже 23 API, то приложение упадет с ClassNotFoundException
.
8. При добавлении нескольких интентов к шорткату, которые обрабатываются разными активностями, можно выстроить определенный стек активностей. Самой нижней в этом стеке будет активность, обработавшая первый добавленный интент.
9. Если пользователь заблокирован на устройстве, то воспользоваться шорткатами у него не получится — они содержатся в зашифрованном хранилище.
10. Если пользователь хочет поддерживать приложение на другом устройстве, то только «закрепленные» шорткаты будут воссозданы на нем. Динамические и статические не воссоздаются, однако статические будут заново определены при установке приложения. Если вас волнует поддержка приложения на разных устройствах, и вы не поставили флаг allowBackup = false
в Манифесте, нужно заботиться только о ручном воссоздании динамических шорткатов.
11. Android developers также предлагают нам использовать метод reportShortcutUsed(String id)
при выполнении действия из соответствующего шортката — как при нажатии на шорткат, так и локально в приложении, если действие то же самое. Как утверждают разработчики, должна быть статистика использования тех или иных действий из шорткатов, и на основе этой статистики пользователю могут предлагаться определенные шорткаты. Возможно, именно здесь должен раскрыться потенциал пятого шортката.
Напоследок парочка еще не упомянутых советов от Android developers.
1. Обновляйте шорткаты (updateShortcuts()
), если их содержание и значение не изменилось, а изменилось только отображаемое сообщение или иконка. Если вы хотите убрать один шорткат и добавить другой, то не используйте обновление, выполните операции удаления, а затем добавления. Пренебрегая этим советом, можно получить разного рода казусы с «закрепленными» шорткатами.
2. Следуйте руководству по дизайну шорткатов. Это небольшой документ, которому нетрудно следовать.
• внутри иконки должен быть простенький значок, вроде плюсика (размер — 24 х 24 dp);
• цвета должны соответствовать общей теме приложения;
• при выборе иконки помните, что она будет отображаться на «закрепленных» шорткатах вместе с основной иконкой приложения справа внизу, поэтому не стоит выбирать что-то наподобие такого:
Заключение
Android Shortcuts – это мощный инструмент работы с приложениями. Серьезные многофункциональные приложения должны использовать его, чтобы следовать в ногу со временем. Надеюсь, это руководство вдохновит вас на добавление такого механизма в свои приложения и поможет внедрить его безболезненно. Не стоит применять в своем приложении шорткаты, если вы знаете, что они там нужны так же, как телеге пятое колесо. Помните об уместности, ведь шорткаты добавляются не для расширения функционала, а для удобства пользователя.
Автор: Тинькофф Банк