Реализация пользовательских шрифтов

Начиная с 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 . Это хранилище защищено. Запись в него может выполнять только FontManagerService в соответствии с политикой SELinux.

При запуске класса 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 , система динамически создает экземпляр шрифта для заданного значения насыщенности и стиля во время выполнения.

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

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

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

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 файлом шрифтов эмодзи вашего OEM-производителя, поместите шрифт эмодзи непосредственно перед цепочкой резервных шрифтов:

  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-производителей. OEM-производители могут установить дополнительные средства обновления шрифтов, выполнив действия, описанные в разделах «Предварительные условия для собраний» , «Подписание файлов шрифтов» и «Обновление шрифтов во время выполнения» .

Соответствовать предварительным условиям

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

Файлы шрифтов для подписи

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

Сделать обновления шрифтов во время выполнения

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

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