Как реализовать пользовательские шрифты

В Android 15 переменные шрифты отрисовываются во время выполнения с большей эффективностью и детализацией. Теперь поставщики должны добавлять новые конфигурации вариативных шрифтов в font_fallback.xml, а не в fonts.xml, так как fonts.xml больше не поддерживается. Подробнее о поддержке вариативных шрифтов…

В Android 11 и более ранних версиях для обновления файлов шрифтов, установленных на устройстве в AOSP (в разделе /system/fonts) или в разделах поставщика (в разделах /product/fonts или /system/fonts), требуется обновление системы от OEM-производителя. Это требование значительно влияет на совместимость эмодзи. В Android 12 вы можете использовать системный сервис FontManager для управления установленными файлами шрифтов и обновления файлов шрифтов, установленных на устройстве, без обновления системы.

В Android 12 есть три типа взаимодействия процессов: FontManagerService, Font Updater и Application.

FontManagerService – это центральная система управления на системном сервере. FontManagerService сохраняет последние настройки системного шрифта для каждого пользователя.

FontUpdater – это подключаемый модуль для обновления шрифтов, который считается доверенным после проверки разрешения signature|privileged. FontUpdater взаимодействует с FontManagerService, чтобы получать, устанавливать, удалять или обновлять текущие настройки системного шрифта. FontUpdater может передавать содержимое нового файла шрифта с помощью механизмов межпроцессного взаимодействия (IPC). При использовании FontManagerService содержимое сохраняется в общедоступном хранилище, например в файлах /data/fonts. Это хранилище охраняется. Согласно правилам SELinux, запись в него может выполнять только FontManagerService.

При запуске класса Application он передает системные настройки шрифта в качестве аргументов метода bindApplication, а затем инициализирует настройки шрифта для использования процессом приложения.

Поддержка вариативных шрифтов

В Android 15 конфигурации переменных шрифтов указываются в элементе font_fallback.xml в следующем формате:

<family lang="und-Ethi" supportedAxes="wght,ital">
    <font>NotoSansEthiopic-VF.ttf</font>
</family>

В этом формате у переменного шрифта есть все атрибуты статического шрифта, а также дополнительный атрибут supportedAxes. Атрибут supportedAxes представляет собой список поддерживаемых тегов осей, разделенных запятыми. В Android 15 можно указать только оси wght и ital.

Если атрибут supportedAxes не указан, узел font работает как статический шрифт одного экземпляра переменного шрифта, заданного с помощью дочерних элементов axis.

Если указан атрибут supportedAxes, система динамически создает экземпляр шрифта с заданным весом и стилем во время выполнения.

Разработчики могут использовать android.graphics.fonts.SystemFonts#getAvailableFonts Java API или ASystemFontIterator_open NDK API, чтобы получить список системных файлов шрифтов. Информацию о том, какие API для разработчиков поддерживают это обновление, можно найти в статьях Улучшенный API для переменных шрифтов OpenType и buildVariableFamily.

Настроить шрифты

Некоторые производители устройств устанавливают или заменяют файлы шрифтов в AOSP, чтобы показывать свои бренды. В Android 12 эта функция поддерживается, но в ней добавлены требования к обновлению шрифтов эмодзи на устройствах. Производителям, которые не изменяют и не обновляют файлы шрифтов эмодзи, эта функция не нужна.

Google обновляет файлы шрифтов, особенно файлы NotoColorEmoji, через GMS Core, поэтому не изменяйте и не удаляйте файл NotoColorEmoji.ttf из раздела /system и не удаляйте его из /frameworks/base/data/fonts/fonts.xml. Обратите внимание на три способа настройки шрифтов:

  1. Замените файл NotoColorEmoji.ttf шрифтом эмодзи с брендингом производителя.
  2. Измените файл NotoColorEmoji.ttf в соответствии с требованиями местного рынка.
  3. Заменять или изменять другие файлы шрифтов.

Если вы не меняете шрифты эмодзи в AOSP, никаких действий не требуется. Если вы хотите настроить шрифты эмодзи, следуйте инструкциям в следующих разделах.

Заменить NotoColorEmoji.ttf на шрифты эмодзи с брендом OEM

Чтобы заменить файл NotoColorEmoji.ttf файлом шрифтов эмодзи с брендом производителя устройства, поместите шрифт эмодзи непосредственно перед цепочкой резервных шрифтов:

  1. Поместите свой шрифт OEMCustomEmoji.ttf в раздел /system.
  2. Измените /frameworks/base/data/fonts/fonts.xml (и /frameworks/base/data/fonts/font-fallback.xml в Android 15 и более поздних версиях), как показано в следующем коде:

    <family lang="ko">
    <font weight="400" style="normal" index="1">NotoSansCJK-Regular.ttc</font>
    </family>
    <!-- ADD FOLLOWING LINE -->
    <family lang="und-Zsye">
       <font weight="400" style="normal">OEMCustomEmoji.ttf</font>
    </family>
    <!-- END OF MODIFICATION -->
    <family lang="und-Zsye">
       <font weight="400" style="normal">NotoColorEmoji.ttf</font>
    </family>
    <family lang="und-Zsym">
       <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
    </family>
    

Измените файл NotoColorEmoji.ttf в соответствии с требованиями местного рынка.

Чтобы настроить презентацию в соответствии с местным рынком, выполните следующие действия:

  1. Создайте собственный файл NotoColorEmoji с другим названием, например Modified\_NotoColorEmoji.ttf.
  2. Поместите его перед исходным файлом NotoColorEmoji.ttf.

После выполнения шага 2 вместо исходного глифа NotoColorEmoji.ttf будет показываться измененный глиф, поддерживаемый Modified\NotoColorEmoji.ttf. Google рекомендует следующее:

  • В шрифте должен быть только нужный глиф.
  • Передайте неизмененные глифы в исходный файл NotoColorEmoji.ttf, чтобы ваши устройства получали исправления дизайна, внесенные в будущих выпусках эмодзи.

Удаление глифов. Чтобы удалить глифы из файла NotoColorEmoji.ttf, выполните шаги 1 и 2 и укажите glyph ID = 0 в cmap.

Используйте региональный флаг. Если целевой глиф – это региональный флаг, укажите идентификатор глифа как неизвестный код страны. (Используйте country code = "ZZ".)

Создайте глиф тофу. Вы можете явно указать идентификатор глифа тофу, если хотите его использовать. Если вы укажете glyphID = 0, связанное приложение интерпретирует это как "глиф недоступен". Например, если вы используете этот атрибут, приложение Paint#hasGlyph возвращает false.

Замена или изменение других файлов шрифтов

Чтобы заменить или изменить другие шрифты, настройка аналогична изменению TTF-файлов для местного рынка. Неизвестные файлы шрифтов, которые обновляются в AOSP во время выполнения, игнорируются и не обновляются. Google игнорирует неизвестные шрифты на устройстве. Это относится и к файлам шрифтов, которые были изменены по сравнению с оригинальными шрифтами в AOSP.

Хотя Google обновляет шрифты в GMS Core, общий механизм обновления шрифтов доступен всем производителям оборудования. OEM-производители могут устанавливать дополнительные средства обновления шрифтов, следуя инструкциям в разделах Предварительные требования, Подписание файлов шрифтов и Обновление шрифтов во время выполнения.

Требования

Для обновления шрифтов используется функция ядра Linux fs-verity. Убедитесь, что ваше устройство соответствует требованиям fs-verity, и добавьте сертификат на устройство.

Как подписывать файлы шрифтов

Поскольку файлы шрифтов являются потенциально опасными ресурсами, их необходимо проверять с помощью надежных ключей. Внимательно проверьте все файлы шрифтов, которые нужно обновить, и подпишите их закрытым ключом. Подпись должна бытьfs-verity совместима.

Обновление шрифтов во время выполнения

Обновление шрифтов выполняется системным приложением FontManager. Приложение FontManager позволяет узнать статус установленного системного шрифта и обновить файлы шрифтов с помощью подписей. Чтобы вызывать обновление приложений, добавьте разрешение UPDATE_FONT signature|privileged в белый список приложений и манифест.

Предоставьте разрешение UPDATE_FONT signature|privileged функции обновления приложения.