0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

现在Android平台也能顺利使用Emoji了

海阔天空的专栏 • 来源:谷歌开发者 • 作者:谷歌开发者 • 2022-06-02 15:08 • 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在移动互联网如此发达的今天,Emoji 已无处不在,并成为我们日常交流中不可或缺的一部分。据统计,Emoji 的使用率在过去 10 年内不断攀升,2021 年更是达到了历史新高,每天有超过五分之一的推文中包含了 Emoji,一些应用上的用户每天发送的 Emoji 数量更是达到了数十亿。然而用户在 Android 平台上使用 Emoji 时却存在着一些问题,本文将针对这些问题进行探讨,并向您介绍 Emoji 的工作原理以及 Android 平台近期关于 Emoji 的更新。

Emoji 在 Android 平台的现状

Emoji 在 Android 平台存在的问题

Unicode 每年都会对 Emoji 标准进行更新,用户越来越频繁地使用各种 Emoji,但却存在有约 96% 的 Android 用户无法正确查看新发布 Emoji 的问题,而 iOS 平台只有 16%,这一比例明显高出许多。

另外根据统计排名,前 100 位的 Emoji 占据了所有用户日常使用 Emoji 总量的 82%,但在约 20% 的情况下,当用户发送一个 Emoji 后,对方看到的却是豆腐块或一张损坏的图像,这种情况直接导致用户无法正确通过 Emoji 来传递自己的本意。如下图所示,用户发送了一张含泪的笑脸,但对方却只收到一个中间有 X 的方块 (我们称其为豆腐块)。

图片

△Emoji 在发送和接受方的不同显示效果

随着用户的增多,Unicode 也在不断增加新的 Emoji 来体现多元化和包容性,但是 Android 却并不能完全兼容这些新版的 Emoji,不同的 Android 版本对 Emoji 的支持程度也不同。比如以下的几个例子:

图片

△Emoji 无法在不同 Android 版本间正确表达多样性和包容性

  1. 在 Android 7.0 Nougat 和更早版本上无法正确通过 Emoji 表示肤色。用户发送了一个表示深肤色手臂的 Emoji,但对方收到的却是一个手臂和深色方块的分解版本。
  2. 在 Android 8.0 Oreo 和更早版本上无法正确显示代表中性的 Emoji。
  3. 在 Android 9 Pie 和更早版本上不支持显示多人多肤色的 Emoji。

Android 平台针对 Emoji 的解决方案

以上问题显然会导致非常糟糕的用户体验,并且不利于用户之间通过 Emoji 进行交流。我们的目标就是确保所有 Android 用户无论是使用哪种应用,都能够正常地使用每个 Emoji。为此,从 Android 12 开始,我们引入了可更新系统字体 (Updatable System Fonts),首先引入的便是 Emoji 字体,这也意味着开发者再也不需要在搭载 Android 12 以及 12 以上版本的设备中考虑 Emoji 适配的问题了,系统将默认支持新的 Emoji。

但是考虑到时光机还没有被发明出来,我们也没办法穿越到过去把可更新系统字体塞到旧版本的设备中去。如果一直等待时光机被发明出来而什么也不做的话,Android 12 版本之前的设备就会一直显示豆腐块,或者以其他错误的方式进行渲染。因此我们还是做了些改进,让您可以通过更新 Jetpack 库

EmojiCompat

解决这一问题:

https://developer.android.google.cn/guide/topics/ui/look-and-feel/emoji-compat

EmojiCompat 早在几年前就已经发布,2021 年我们对其做了很多改进,并将其整合至AppCompat 1.4版本中。为此我们开发了一个新库 androidx.emoji2,并添加了自动配置选项,它可自行配置以加载正确的字体。我们将这个库集成到了 AppCompat 1.4 中,也就是说,您仅需升级至 AppCompat 1.4 版本,便可在 API 19 及更高的版本上正常显示新加入的 Emoji,开箱即用,无需任何额外配置。

  • AppCompat 1.4 版本
    https://developer.android.google.cn/jetpack/androidx/releases/appcompat#1.4.1
  • androidx.emoji2
    https://developer.android.google.cn/jetpack/androidx/releases/emoji2


AppCompat 1.4 针对 Emoji 的优化

图片

△Emoji2 和 Emoji 对比

Emoji2 库是 AppCompat 库的一个新的依赖项,虽然它会代替现有的 androidx.emoji 库,但是 API 几乎相同。在此次更新中,我们使用 androidx.startup 添加了新的初始化程序 (EmojiCompatInitializer),添加了新的默认配置,并且全部支持了 nullability 注解。另外,相较于 androidx.emoji,我们还删除了一些在使用 AppCompat 时不再需要的 TextView 子类,这使得在 RA 之后节省了约 14KB 的大小。

  • Emoji2https://developer.android.google.cn/jetpack/androidx/releases/emoji2
  • androidx.emojihttps://developer.android.google.cn/jetpack/androidx/releases/emoji

图片

△Emoji2 加载 Emoji 的步骤

在这次更改中,一大新特性便是 EmojiCompatInitializer,它是一个使用了 androidx.startup 库的初始化程序,在应用启动时会自动配置 EmojiCompat。我们已对该初始化程序的性能进行了大量的调整,对于大多数应用来说使用默认配置已经完全足够,但如果您需要对应用启动做纳秒级别的优化,则可以考虑移除 startup 库和创建线程所带来的消耗。首先,确保先初始化 EmojiCompat,再执行 Activity.onCreate,这可以保证每个 TextView 都能显示新版 Emoji。然后,可以像 EmojiCompatInitializer 一样将 Emoji 字体加载延迟到首屏绘制之后,这样做是因为虽然加载过程是在后台线程中进行的,但它还是执行大量的网络和磁盘 I/O 操作,这些操作会同首屏加载一起抢夺资源。

这里再次强调,我们已对该初始化程序的性能进行了大量的调整和优化,除非必要,请使用 EmojiCompatInitializer 的默认实现。

pYYBAGKYYU6ARxuEAABPGqHk-_s700.png


另一个重要的功能是默认配置,在 androidx.emoji 中您需要从文档的示例代码中复制一些模版配置 (类似于以上代码) 到应用中,而 Emoji2 中我们添加了可以直接用于 EmojiCompatInitializer 的 DefaultEmojiCompatConfig,如下代码所示,只需一行简单配置即可,当然也支持手动配置的需求。

poYBAGKYYVOAFkV5AAAeVOGNZ3Q502.png

在 AppCompat 中,我们将 Emoji2 集成到了所有的视图中,这意味着所有视图都可以支持新版 Emoji,如果您的 Activity 继承了 AppCompatActivity,在 XML 中直接使用 TextView 或 EditView 即可。AppCompatActivity 安装了一个布局填充器 (LayoutInflater),它会用 AppCompatTextView 来替换 TextView 等视图,在代码中无论何时创建 TextView,都应该确保创建的是 AppCompatTextView,并且自定义视图应该继承相应的 AppCompat 子类。
所有集成了 Emoji2 的视图都有一个 EmojiCompatEnabled 属性,通过它可以控制是否开启 EmojiCompat,该属性还提供了 getter 和 setter 方法。EmojiCompatEnabled 属性有助于在知道文本绝不可能包含 Emoji 的情况下,来规避执行 Emoji 的处理逻辑,虽然即使不规避该逻辑所带来的成本也是极低的,但在某些情况下每一纳秒都至关重要,此属性便是为了支持这种情况。另外,该属性对于在后台线程上处理 Emoji 也很有帮助,AppCompat 对于 Emoji2 的集成会在 setText 之后的适当时间调用 EmojiCompat.process,您可以通过 EmojiCompatEnabled 属性禁用此方法调用,并对 Emoji 的处理移至后台线程。但通常这种优化没必要,除非是在 RecyclerView 中展示大量的文本导致卡顿,那么可以考虑采用这一优化方案。

测试新版 Emoji

由于集成了可下载字体,对于测试新版的 Emoji 并不是那么容易。要创建一个不会导致误报或漏报的通用自动化测试库很难,而大多数开发者在实际情况下会直接手动测试 EmojiCompat 的集成,因此最好的选择还是使用一个记录了用于测试的 Emoji 列表,同样此方式对于手动测试或对屏幕截图进行测试也都非常有用。


如果您希望了解更多信息,请查看文档:支持新式表情符号。我们在文档中为您提供了一些关于配置测试模拟器和设备所需要的一些操作建议:

https://developer.android.google.cn/guide/topics/ui/look-and-feel/emoji2

Emoji 渲染原理


图片

△一组码点

Emoji 属于一种图形字符,是字符串的一部分。它就像字母 "I"一样,只是绘制方式和从属的字体文件不同而已。但是对于计算机来说,它并不会特意关心什么是 Emoji 或字母 "I",一个字符串本质上就只是一组码点,其中的数字通过 Unicode 进行分配,代表着计算机上会出现的每一个字符。

现在 Unicode 并不仅仅只是一种格式了,它还代表了制定该标准的委员会,委员会会决定一些事情,比如数字 7 代表字母 "I" (实际上 7 并非真正代表字母 I 的码点,此处仅仅是举个例子)。那么当您试图在 Android 上渲染上述表示字符串的码点时会发生什么呢?


首先,Android 会根据码点和应用要求使用的字体样式为每个字符找出最佳字体。当前 Android 上非斜体且正常粗细 "V"的默认字体是 roboto-regular.ttf,Android 会对字符串进行遍历,检查每个字符并查找最佳字体。它会检查码点和样式,您可以对字符串进行样式的定制操作,比如对一些字符进行加粗等等。对于上述简单的字符串来说,它就只是会选择 roboto-regular.ttf 字体。

图片

△遍历码点查找正确的字符串

但是,当遇到 Emoji 字符时,您可能会觉得它会进行完全不同的渲染方式,毕竟它看起来不像任何其他的字母。但实际上,Emoji 就是个文本,由码点表示,同字母 "I"和 "I"一样没什么区别,绘制它的方式就存储到了字体中。Android 会首先尝试在字体中查找无斜体且正常粗细的 "融化脸",但这一次发现在 roboto-regular 中并没有想要的结果,便会去 NotoColorEmoji 中进行查找,这是 AOSP 上预装的 Emoji 字体,它包含了每个 Emoji 的图像,在 Android 平台上通过这种字体绘制 Emoji 和绘制字母 "I"的方式完全相同,都是查找字体文件后在屏幕上绘制出来。

图片

△通过 NotoColorEmoji 对 Emoji 字符进行绘制

在 Android 12 及以上版本中,平台可以确保 Emoji 会正常显示,因为可更新系统字体会将新版 Emoji 添加到字体文件中。但对于 Android 12 之前的版本,我们没有任何方法可以更新字体,这意味着 Android 不知道用什么字体来绘制 "融化脸",此时它会改为绘制一个称为豆腐块的备用字形。这里就是 Emoji2 开始大展身手的地方了。

图片

△Emoji2 对 Emoji 字符的绘制过程

在将字符串发送到 Android 系统之前,在字符串上会调用 EmojiCompat.process 方法,此调用将遍历并查找那些系统不知道如何绘制的 Emoji,并为每个 Emoji 添加一个 EmojiSpan,这是一个替换 Span,这意味着它将只替换该段字符串中对应的内容。系统会直接使用 roboto-regular.ttf 正常绘制,但当找到 EmojiSpan 时它会将绘制权转交给 Span。


在该 Span 中 Android 使用了两个方法,首先,它会获取字符尺寸并告诉 Android 要在文本布局中为此 Span 保留多少空间,然后,当需要绘制字符串时,它将调用 EmojiSpan 上的 draw 而非自行绘制。在 EmojiSpan 中,它知道 Compat 版的 Emoji 字体位置,并能直接从中绘制出 "融化脸"。再返回到渲染阶段,平台将调用 EmojiSpan.draw,整个区域将由 EmojiSpan 进行绘制,而非平台。实际上,从平台的角度来看 EmojiSpan 只是在字符串中间绘制了一张图片,并没有别的特殊操作。

总结

本文通过分析 Emoji 在 Android 平台存在的问题,针对不同版本的 Android 系统介绍了两种解决方案:

  • Android 12 及以上的版本使用可更新系统字体,无需开发者手动适配;
  • Android 12 以下的版本集成 AppCompat 1.4 也可自动适配新版 Emoji,无需额外操作。

此外,我们还介绍了 Emoji 的渲染原理,让您更进一步了解 Emoji 是如何呈现在屏幕上的。请记得升级 AppCompat 到 1.4 版本,为用户提供支持新版 Emoji 的最佳体验。

来源:谷歌开发者

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Andorid
    +关注

    关注

    0

    文章

    7

    浏览量

    7340
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Android 15来了!系统、功能、体验三重升级,米尔MYD-LR3576开发板

    15,V2.0.1 不仅更新了系统平台,也将更实用的摄像头、无线并发能力和调试体验纳入正式版本。 对比项 V1.0.0 V2.0.1 Android版本
    发表于 09-24 17:55

    瑞能半导体2026亚太经销商大会顺利举办

    8月5‑6日,瑞能半导体2026亚太经销商大会在泰国芭堤雅顺利举办。本次大会汇聚来自东盟、日本、韩国、印度等亚太各区域核心经销商与行业合作伙伴,搭建起高效的沟通交流平台,共话行业趋势,深化渠道协作,锚定未来市场发展方向。
    的头像 发表于 08-11 17:18 •360次阅读

    紫光展锐多款移动平台完成Android 17同步升级

    近日,紫光展锐完成 Android 17 同步升级,旗下 T8300、T7300、T7250 等移动平台已完成新版本适配验证,持续保持与 Android 最新版本同步节奏,为终端厂商导入新系统、优化用户体验提供
    的头像 发表于 07-20 13:46 •466次阅读

    上能电气顺利供货阿尔及利亚多个光伏电站

    近日,上能电气向阿尔及利亚多个光伏电站顺利完成供货,总容量达154MW,为北非地区能源转型注入强劲动力,开启了绿色能源发展的新篇章。
    的头像 发表于 07-13 16:52 •427次阅读

    上能电气助力云南150MW/300MWh储能电站顺利完成黑启动测试

    近日,由上能电气供货的永德150MW/300MWh全构网型储能电站迎来突破性进展——顺利完成场站级黑启动试验。此次测试不仅充分验证了场站在极端情况下自主启动并恢复供电的能力,为区域电网
    的头像 发表于 07-08 14:20 •381次阅读

    AD9361通过ILA抓数观察也能采集到正弦波信号,但是data_clk不规律为什么

    Category: Hardware Product Number: AD9361 通过SPI配置了1T1R,COMS,dual port,FDD,DDR模式,能够顺利发射出正弦波,通过
    发表于 06-26 07:02

    上能电气助力南非120MW多恩胡克光伏电站顺利并网

    近日,由上能电气供货的南非120MW多恩胡克Doornhoek光伏电站顺利完成所有机器的调试工作,目前该项目已成功全容量并网。这一项目的落成,不仅丰富了南非的可再生能源资源储备,也为该
    的头像 发表于 04-27 16:53 •904次阅读

    Google正式发布LLM评测基准Android Bench

    LLM 在 Android 开发任务中的表现。现在,我们发布了 Android Bench 的首个版本,这是 Google 官方专门针对 Andr
    的头像 发表于 03-14 16:00 •2305次阅读
    Google正式发布LLM评测基准Android Bench

    中车永济电机公司首台兆瓦级飞轮储能电机样机顺利交付

    近日,中车永济电机公司顺利完成首台兆瓦级飞轮电机样机顺利交付。该项目是飞轮储能调频市场中大功率段标杆产品,标志着公司在中大功率飞轮储能核心装备研发制造领域实现关键突破。
    的头像 发表于 01-24 15:52 •2403次阅读

    深入解析rk平台Android Bootloader核心代码:从启动流程到AVB验证

    作为Android设备启动的第一道“闸门”,Bootloader(以U-Boot为主)承担着初始化硬件、加载内核、验证镜像完整性的核心职责。今天我们拆解Rockchip平台
    的头像 发表于 01-22 07:06 •977次阅读
    深入解析rk平台Android Bootloader核心代码:从启动流程到AVB验证

    深入解析RK平台Android/Linux Bootloader核心文件:android_bootloader.c

    _bootloader.c是对接Android启动逻辑的核心文件——它决定了设备是进入正常系统、Recovery模式还是Fastboot模式,同时承担了AVB(Android Veri
    的头像 发表于 01-09 10:58 •2005次阅读
    深入解析RK平台Android/Linux Bootloader核心文件:android_bootloader.c

    上能电气向印度Khavda能源基地顺利交付576MW储能变流器

    近日,上能电气向印度Khavda能源基地顺利交付576MW储能变流器。此次交付标志着上能电气在印度储能市场战略推进中取得重要突破,也为公司海
    的头像 发表于 12-28 10:40 •1262次阅读

    晶科储能5MWh储能系统顺利运抵澳洲市场

    晶科储能近日宣布其 5MWh 级储能系统核心设备已顺利运抵澳大利亚,用于支持澳洲矿业及相关混合能源应用场景,标志着晶科储能在澳洲矿业储能市场的持续深化布局。
    的头像 发表于 12-23 17:40 •1656次阅读

    鸿蒙系统对手机市场会产生怎样的影响?现在汽车是不是也用上鸿蒙系统了?

    鸿蒙系统对手机市场会产生怎样的影响?现在汽车是不是也用上鸿蒙系统了?
    发表于 12-04 20:47

    淘宝API赋能,小卖家也能拥有大格局!

    提供的丰富 API 接口,正成为小卖家实现“弯道超车”的利器。借助这些 API,小卖家也能拥有管理海量商品、服务万千客户、洞悉市场趋势的“大格局”能力。 一、淘宝API:小卖家的“技术外挂” 淘宝开放平台提供
    的头像 发表于 12-04 14:27 •776次阅读
    淘宝API赋能,小卖家也能拥有大格局!