The standard set of emoji is refreshed annually by Unicode, with usage of emoji by users increasing rapidly for all types of apps.
If your app displays Internet content or provides text input, we strongly recommend supporting the latest emoji fonts. Otherwise, newer emoji may be displayed as a small square box called tofu (☐) or other incorrectly rendered emoji sequences.
Versions of Android 11 (API level 30) and lower don't have the ability to update the emoji font, so any app that displays them on those lower versions must be updated manually.
The following are some examples of modern emoji.
Examples | Version |
---|---|
🫠 🫱🏼🫲🏿 🫰🏽 | 14.0 (September 2021) |
😶🌫️ 🧔🏻♀️ 🧑🏿❤️🧑🏾 | 13.1 (September 2020) |
🥲 🥷🏿 🐻❄️ | 13.0 (March 2020) |
🧑🏻🦰 🧑🏿🦯 👩🏻🤝👩🏼 | 12.1 (October 2019) |
🦩 🦻🏿 👩🏼🤝👩🏻 | 12.0 (February 2019) |
The androidx.emoji2:emoji2
library provides simpler backward-compatibility
with lower versions of Android. The emoji2
library is a dependency of the
AppCompat
library and requires no further
configuration to work.
Prerequisites
To confirm that your app properly displays newer emoji, launch it on a device running a version between Android 4.4 (API level 19) and Android 11 (API level 30) inclusive. This page includes modern emoji you can display for testing.
Use AppCompat to support the latest emoji
AppCompat 1.4 includes support for emoji back to Android 4.4.
To use AppCompat to support the latest emoji:
Check that your module depends on the
appcompat
library version 1.4.0-alpha01 or higher.build.gradle // Ensure version is 1.4.0-alpha01 or higher. implementation "androidx.appcompat:appcompat.$appcompatVersion"
Ensure all activities that display text extend the
AppCompatActivity
class.Kotlin
MyActivity.kt class MyActivity: AppCompatActivity { … }
Java
MyActivity.java class MyActivity extends AppCompatActivity { … }
To test your integration, launch your app on a device running Android 11 or lower, and display the following test string. Make sure that all characters render correctly.
- 14.0: 🫠, 🫱🏼🫲🏿, 🫰🏽
- 13.1: 😶🌫️, 🧔🏻♀️, 🧑🏿❤️🧑🏾
- 13.0: 🥲, 🥷🏿, 🐻❄️
- 12.1: 🧑🏻🦰, 🧑🏿🦯, 👩🏻🤝👩🏼
- 12.0: 🦩, 🦻🏿, 👩🏼🤝👩🏻
That's it! Your app automatically displays backward-compatible emoji on all
devices that provide an emoji2
-compatible downloadable fonts provider, such as
devices powered by Google Play
services.
If your app is using AppCompat but displays tofu (☐)
In some cases, your app may display tofu (☐) instead of the proper emoji, even though you've added the AppCompat library. The following are some possible explanations and solutions.
You're running the app on a recently-flashed device or a brand new emulator
Clear the app data for Google Play services to clear any font caching that may have happened during startup. Once you do so, this situation typically resolves itself after a few hours.
To clear the app data:
On your Android device, open Settings.
In Settings, tap Apps & notifications.
Tap See all apps or App info.
Scroll through the apps, and tap Google Play services.
Tap Storage & cache.
Tap Clear cache.
Your app isn't using an AppCompat text-related class
This can happen if you don't extend AppCompatActivity
, or if you instantiate a
view in code such as TextView
. Make sure that you do the following:
- The activity extends
AppCompatActivity
. - If creating the view in code, use the correct
appcompat subclass
.
AppCompatActivity
automatically inflates AppCompatTextView
in place of
TextView
when inflating XML, so you don't need to update your XML.
The test phone doesn't support downloadable fonts
Verify that DefaultEmojiCompatConfig.create
returns a non-null configuration.
An emulator on an older API level hasn't upgraded Google Play services
When using an emulator on an older API level, the bundled Google Play services
may need to be upgraded for emoji2
to find the font provider. To do this, log
in to the Google Play Store on the emulator.
To verify that a recent enough version has been installed, do the following:
Running the following command:
adb shell dumpsys package com.google.android.gms | grep version
Check that the
versionCode
is higher than211200000
.
Support emoji without AppCompat
If your app doesn't include appcompat
, it can use emoji2
directly. This
requires more work, so use this method only if your app cannot
use appcompat
.
To support emoji without the AppCompat library, do the following:
In your app's
build.gradle
file, includeemoji2
andemoji2-views
.build.gradle def emojiVersion = "1.0.0-alpha03" implementation "androidx.emoji2:emoji2:$emojiVersion" implementation "androidx.emoji2:emoji2-views:$emojiVersion"
The
emoji2-views
module provides subclasses ofTextView
,Button
, andEditText
that implementEmojiCompat
, and should not be used in an app that includesappcompat
because it already implementsEmojiCompat
.In XML or code (wherever you would use
TextView
,EditText
, orButton
), useEmojiTextView
,EmojiEditText
, orEmojiButton
instead.activity_main.xml <androidx.emoji2.widget.EmojiTextView … /> <androidx.emoji2.widget.EmojiEditText … /> <androidx.emoji2.widget.EmojiButton … />
By including the
emoji2
module, the system uses the default downloadable fonts provider to load the emoji font automatically shortly after app startup, and no further configuration is needed.To test your integration, launch your app on a device running Android 11 or lower, and display the following test strings. Make sure that all characters render correctly.
- 14.0: 🫠, 🫱🏼🫲🏿, 🫰🏽
- 13.1: 😶🌫️, 🧔🏻♀️, 🧑🏿❤️🧑🏾
- 13.0: 🥲, 🥷🏿, 🐻❄️
- 12.1: 🧑🏻🦰, 🧑🏿🦯, 👩🏻🤝👩🏼
- 12.0: 🦩, 🦻🏿, 👩🏼🤝👩🏻
Use EmojiCompat without widgets
EmojiCompat
uses
EmojiSpan
to render correct
images. Therefore, it has to convert any given [CharSequence
] object into a
Spanned
object with EmojiSpan
objects.
The EmojiCompat class provides the process()
method to convert CharSequences
into Spanned
instances. Using this method, you can call process()
in the
background and cache results, which improves the performance of your app.
Kotlin
val processed = EmojiCompat.get().process("neutral face \uD83D\uDE10")
Java
CharSequence processed = EmojiCompat.get().process("neutral face \uD83D\uDE10");
Use EmojiCompat for input method editors
The EmojiCompat
class allows
keyboards to render the emoji supported by the app they are interacting with.
Input method editors (IMEs) can use
the hasEmojiGlyph()
method to check whether an instance of EmojiCompat
is capable of rendering an
emoji. This method takes a CharSequence
of an emoji and returns true
if EmojiCompat
can detect and render the emoji.
The keyboard can also check the version of EmojiCompat
that the app supports
to determine which emoji to render in the palette. To check the version, if
available, the keyboard can look for the following keys in the
EditorInfo.extras
bundle:
EDITOR_INFO_METAVERSION_KEY
: Represents the version of the emoji metadata that the app uses. If this key doesn't exist, then the app isn't usingEmojiCompat
.EDITOR_INFO_REPLACE_ALL_KEY
: If the key exists and is set totrue
, then the app has configuredEmojiCompat
to replace all emoji, even if they are present in the system.
Learn more about how to configure an instance of EmojiCompat.
Use emoji in custom views
If your app has custom views that are
direct or indirect subclasses of TextView
(for example, Button
, Switch
, or
EditText
) and can display user-generated content, they should each implement
EmojiCompat.
The process is different depending on whether your app uses the appcompat
library.
Add custom views for apps with AppCompat
If your app uses AppCompat, extend the AppCompat implementation instead of the platform implementation. Use the following table as a guide for how to extend your views in AppCompat:
Instead of extending... | Extend |
---|---|
TextView
|
AppCompatTextView
|
EditText
|
AppCompatEditText
|
ToggleButton
|
AppCompatToggleButton
|
Switch
|
SwitchCompat
|
Button
|
AppCompatButton
|
CheckedTextView
|
AppCompatCheckedTextView
|
RadioButton
|
AppCompatRadioButton
|
CheckBox
|
AppCompatCheckBox
|
AutoCompleteTextView
|
AppCompatAutoCompleteTextView
|
MultiAutoCompleteTextView
|
AppCompatMultiAutoCompleteTextView
|
Add custom views for apps without AppCompat
If your app doesn't use appcompat
, use the view integration helpers in the
emoji2-views-helper
module that are designed for use in custom views. These
are the helpers that the appcompat
library uses to implement emoji support.
Complete the following steps to support custom views for apps that don't use
appcompat
.
Add the
emoji2-views-helper
library.implementation "androidx.emoji2:emoji2-views-helper:$emojiVersion"
Follow the instructions to include EmojiTextViewHelper or EmojiEditTextHelper in your app's custom views.
To test your integration, launch your app on a device running Android 11 or lower, and display the following test string. Make sure that all characters render correctly.
- 14.0: 🫠, 🫱🏼🫲🏿, 🫰🏽
- 13.1: 😶🌫️, 🧔🏻♀️, 🧑🏿❤️🧑🏾
- 13.0: 🥲, 🥷🏿, 🐻❄️
- 12.1: 🧑🏻🦰, 🧑🏿🦯, 👩🏻🤝👩🏼
- 12.0: 🦩, 🦻🏿, 👩🏼🤝👩🏻
Optional features for handling emoji2
After you include the emoji2
library in your app, you can choose to add the
optional features that are described in this section.
Configure emoji2 to use a different font or downloadable font provider
To configure emoji2
to use a different font or downloadable font provider, do
the following:
Disable the
EmojiCompatInitializer
by adding the following to your manifest.<provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer" tools:node="remove" /> </provider>
Do one of the following:
- Use the default configuration by calling
DefaultEmojiCompatConfiguration.create(context)
. - Create your own configuration to load fonts from another source using
EmojiCompat.Config
. This class provides several options to modify your EmojiCompat behavior.
- Use the default configuration by calling
Modify your EmojiCompat behavior
You can use an instance of
EmojiCompat.Config
to
modify EmojiCompat
behavior.
The most important configuration option is
setMetadataLoadStrategy()
,
which controls when EmojiCompat
loads the font. Font loading begins as soon as
EmojiCompat.load()
is called, and this will trigger any necessary downloads.
The system creates a thread for font downloading unless your app provides one.
LOAD_STRATEGY_MANUAL
allows you to control when EmojiCompat.load()
is called, and
LOAD_STRATEGY_DEFAULT
causes loading to start synchronously in the call to
EmojiCompat.init()
.
Most apps should use LOAD_STRATEGY_MANUAL
to allow control over the thread and
timing of font loading. In particular, your app should defer until after the
first screen displays to avoid introducing startup latency.
EmojiCompatInitializer
follows this practice and defers loading the emoji font
until after the first screen has resumed.
You can use the following methods from the base class to set other aspects of the configuration:
setReplaceAll()
: Determines whetherEmojiCompat
should replace all emoji it finds with instances ofEmojiSpan
. By default, whenEmojiCompat
infers that the system can render an emoji, it doesn't replace that emoji. When set totrue
, EmojiCompat replaces all emoji withEmojiSpan
objects.setEmojiSpanIndicatorEnabled()
: Indicates whetherEmojiCompat
has replaced an emoji with anEmojiSpan
object. When set totrue
,EmojiCompat
draws a background for theEmojiSpan
. This method is mainly used for debugging purposes.setEmojiSpanIndicatorColor
: Sets the color to indicate anEmojiSpan
. The default value isGREEN
.registerInitCallback()
: Informs an app about the state of theEmojiCompat
initialization.
Add initialization listeners
EmojiCompat
and
EmojiCompat.Config
classes provide the
registerInitCallback()
and
unregisterInitCallback()
methods to register and unregister initialization callbacks. Your app uses these
callbacks to wait until EmojiCompat
is initialized before you process emoji on
a background thread or in a custom view.
To use these methods, create an instance of the
EmojiCompat.InitCallback
class. Call these methods and pass in the instance of the
EmojiCompat.InitCallback
class. When the initialization is successful, the
EmojiCompat
class calls the
onInitialized()
method. If the library fails to initialize, the EmojiCompat class calls the
onFailed()
method. To check the initialization state at any point, call the
getLoadState()
method. This method returns one of the following values:
LOAD_STATE_LOADING
,
LOAD_STATE_SUCCEEDED
, or
LOAD_STATE_FAILED
.
Support bundled fonts with emoji2
You can use the emoji2-bundled
artifact to bundle an emoji font into your app.
However, because the current NotoColorEmoji
font is over 10 MB, we strongly
recommend that your app uses downloadable fonts when possible. The emoji2-
bundled
artifact is intended for use for apps on devices that don't support
downloadable fonts.
To use the emoji2-bundled
artifact, do the following:
Include
emoji2-bundled
andemoji2
artifacts.implementation "androidx.emoji2:emoji2:$emojiVersion" implementation "androidx.emoji2:emoji2-bundled:$emojiVersion"
Configure
emoji2
to use the bundled configuration.Kotlin
EmojiCompat.init(BundledEmojiCompatConfig(context))
Java
EmojiCompat.init(new BundledEmojiCompatConfig(context));
Test the integration by following the steps above for including
emojicompat
with or withoutappcompat
, then ensuring the test string displays correctly.- 14.0: 🫠, 🫱🏼🫲🏿, 🫰🏽
- 13.1: 😶🌫️, 🧔🏻♀️, 🧑🏿❤️🧑🏾
- 13.0: 🥲, 🥷🏿, 🐻❄️
- 12.1: 🧑🏻🦰, 🧑🏿🦯, 👩🏻🤝👩🏼
- 12.0: 🦩, 🦻🏿, 👩🏼🤝👩🏻
Impact of automatic EmojiCompat configuration
The system applies default configuration using the startup library, EmojiCompatInitializer, and DefaultEmojiCompatConfig.
Shortly after the first activity resumes in your app, the initializer schedules emoji font loading. This brief delay allows your app to display its initial content without any potential latency due to font loading in a background thread.
DefaultEmojiCompatConfig
looks for a system-installed downloadable font
provider that implements the EmojiCompat interface, such as Google Play
services. On devices powered by Google Play services, this loads the font using
Google Play services.
The initializer creates a background thread to load the emoji font, and font
download may take up to 10 seconds before timing out. After the font is
downloaded, it takes approximately 150 milliseconds on a background thread to
initialize EmojiCompat
.
Defer the initialization of EmojiCompat
, even if you disable
EmojiCompatInitializer
. If you manually configure
EmojiCompat, call EmojiCompat.load()
after the first screen
of your app displays to avoid background contention with first screen load.
After loading, EmojiCompat uses about 300KB of RAM to hold the emoji metadata.