Динамическое изменение иконки приложения
Итак, 2024 год подходит к концу. Пришло время подведения итогов, финальных релизов и обновления иконки для праздничного настроения. Стоит отметить, что наша команда не раз задумывалась о динамическом изменении иконки, независимо от релизного поезда. Мы реализовали данный подход, набили шишек и решили поделиться своим опытом.
- Постановка задачи
- Реализация динамического переключения иконки на iOS
- Реализация динамического переключения иконки на Android
- На что опираться для переключения иконки
Изменение иконки приложения без обновления версии приложения в сторах
С таким заголовком задачи встретилась наша команда в начале спринта. Основная идея состояла в отрыве зависимости от релизного поезда.
Гипотеза заключалась в том, что это позволит снизить риски отсутствия обновления иконки перед каким-либо значимым праздником или событием:
- шанс отмены релиза крайне низкий, но никогда не равен нулю;
- даты старта или завершения релиза могут не подходить для предстоящего события;
- пользователь может не обновлять приложение долгое время и ходить с новогодним дизайном даже летом.
Если вы столкнулись с такой задачей или вас посещала мысль о воплощении такой идеи, но лапки так и не дошли, то делимся своим опытом и шагами для реализации.
Реализация динамического переключения иконки на iOS
Механизм реализации альтернативных иконок стал доступен с iOS 10.3 и идеально подходит для сезонных акций, тематических обновлений или других целей.
Шаг 1: Подготовка иконок
Для начала подготовьте альтернативные иконки в двух размерах: 120px и
180px. Назовите их следующим образом:
Создайте директорию в вашем проекте, где будут хранится файлы изображений.
Шаг 2: Настройка Info.plist
Добавьте в ваш Info.plist
ключ CFBundleIcons
и его под-ключ CFBundleAlternateIcons
. Пример конфигурации:
Здесь мы добавили две альтернативные иконки: Winter и Spring. Чтобы обращаться к ним, используйте значение ключа key
. Название иконки должно совпадать с именем файла, но без суффиксов @2x
и @3x
.
Шаг 3: Создание AppIconManager
Для удобной работы создадим синглтон AppIconManager
. Пример реализации:
supportsAlternateIcons
— проверяет, поддерживает ли приложение смену иконок;alternateIconName
— возвращает текущую альтернативную иконку;setAlternateIconName
— устанавливает новую иконку, используя название ключаkey
изInfo.plist
.
Примечание: Если вы хотите вернуть стандартную иконку, передайте nil
в параметр setAlternateIconName
.
Шаг 4: Использование AppIconManager
Теперь достаточно одной строки кода, чтобы сменить иконку:
Результат
Как убрать системное уведомление при смене иконки
По умолчанию, iOS уведомляет пользователя о смене иконки. Apple не предоставляет официального способа отключить это сообщение, но есть способ его обойти. Для этого обновим функцию setAppIcon
:
ВАЖНО! Почему такой вариант небезопасен?
Не рекомендуем использовать данное решение как минимум по трем причинам:
- Данное решение противоречит релизной политике Apple и может быть отклонено тестировщиком на этапе проверки в AppStoreConnect;
- Небезопасный вызов метода.
unsafeBitCast
предполагает, что сигнатура функции совпадает сsetAlternateIconName
. Если есть расхождение, это может привести к повреждению памяти или сбоям; - Поскольку
_setAlternateIconName:completionHandler:
не документирован, его поведение может измениться в будущих версиях iOS. Это может привести в лучшем случае к некорректному выполнению функции, в худшем к крашу приложения.
Поэтому используйте это решение на свой страх и риск 😅
Реализация динамического переключения иконки на Android
В Android иконка приложения указывается в файле AndroidManifest.xml
и для её переопределения лучше использовать activity-alias, который служит для создания "ссылок" на существующую Activity
.
Шаг 1: Подготовка иконок
На данном этапе подготовка иконок происходит аналогично процессу создания иконки приложения по умолчанию, стоит лишь переименовать ресурсы согласно типу альтернативной иконки ic_winter
и ic_spring
.
Если вы никогда не сталкивались с процессом смены иконки приложения, то стоит ознакомиться с уроком от Google по данной части.
Шаг 2: Настройка activity-alias в AndroidManifest.xml
Ключевыми атрибутами activity-alias
являются:
android:name
— имяalias
-компонента;android:targetActivity
— целеваяActivity
, которую можно открыть черезalias
;android:enabled
— флаг позволяющий управлять состояниемalias
;android:icon
— задаёт иконку дляalias
;android:label
— задаёт название дляalias
.
В AndroidManifest.xml
связываем alias
каждого типа с Activity
, которая позволяет открыть приложение:
Шаг 3: Добавим немного красоты
Для удобства на следующем шаге, можно вынести имя alias
-компонентов в отдельный файл, создав классы Activity
с идентичным именем из AndroidManifest.xml
:
После, подготовить enum-класс с типами:
Шаг 4: Измените активный activity-alias с помощью PackageManager
Создаём метод, который включает нужный alias
и отключает остальные.
Результат
Подводные камни
Настоятельно рекомендуем заранее продумать и предложить дизайнеру отобразить AlertDialog или BottomSheet по аналогии с iOS, чтобы предупредить пользователя о смене иконки приложения. Это связано с тем, что приложение будет закрыто на Android 13 и выше, несмотря на указанный PackageManager.DONT_KILL_APP
.
Реализация AlertDialog или BottomSheet позволит создать безопасную обвязку для поставленной задачи и не вызывать метод смены конфигурации в onStop
. Выполнение логики смены конфигурации в методах жизненного цикла может повлечь за собой баги.
Например, для SingleActivity приложений при смене языка потребуется осуществить пересоздание Activity
, тем самым вызвав onStop
, что приведёт к уничтожению экземпляра приложения, если иконка не соответствует ожидаемой.
На что опираться для переключения иконки
Здесь возможны различные варианты.
Если в вашей компании существует механизм feature-toggle и соответствующее API - оно может подойти для данной задачи.
Если такого механизма нет, можно обратить внимание на Firebase Remote Config.
На этом наш пост подошёл к концу. Всем праздничного настроения и высокого Crash-free во время выходных. Good coding and happy day!🤘
Полезные ссылки:
- Документация по альтернативным иконкам для iOS
- Документация по AndroidManifest.xml
- Документация по activity-alias
- Документация по Firebase Remote Config