Compatibilidade com emojis

O objetivo da Biblioteca de Suporte EmojiCompat é manter os dispositivos Android atualizados com os emojis mais recentes. Ela evita que seu app mostre caracteres ausentes de emojis na forma de ☐, que indica que seu dispositivo não tem uma fonte para exibir o texto. Ao usar a Biblioteca de Suporte EmojiCompat, os usuários do seu app não precisam esperar por atualizações do SO do Android para ter os emojis mais recentes.

Dispositivos mostrando emojis
Figura 1. Comparação de emojis.

Confira os seguintes recursos relacionados:

  • Amostra do app Emoji Compatibility (em inglês) Java | Kotlin

Como a EmojiCompat funciona?

A Biblioteca de Suporte EmojiCompat oferece classes para implementar a compatibilidade com emojis em versões anteriores nos dispositivos com o Android 4.4 (API nível 19) e versões posteriores. Você pode configurar EmojiCompat com fontes agrupadas ou disponíveis para download. Para mais informações sobre a configuração, consulte as seguintes seções:

A EmojiCompat identifica um emoji para uma CharSequence específica, o substitui por um EmojiSpans se necessário e, por fim, renderiza os glifos do emoji. A Figura 2 demonstra o processo.

Processo da EmojiCompat
Figura 2. Processo da EmojiCompat.

Configuração de fontes disponíveis para download

Essa configuração usa o recurso "Fontes para download" da Biblioteca de Suporte para salvar uma fonte de emojis. Ela também atualiza os metadados de emoji necessários que a Biblioteca de Suporte EmojiCompat precisa para acompanhar as versões mais recentes da especificação Unicode.

Adicionar dependência da Biblioteca de Suporte

Para usar a Biblioteca de Suporte EmojiCompat, é necessário modificar as dependências do caminho de classe do seu projeto do app no ambiente de desenvolvimento.

Para adicionar uma Biblioteca de Suporte ao projeto do aplicativo:

  1. Abra o arquivo build.gradle do aplicativo.
  2. Adicione a Biblioteca de Suporte à seção dependencies.
    dependencies {
        ...
        implementation "com.android.support:support-emoji:28.0.0"
    }
    

Inicializar a configuração de fonte disponível para download

É necessário inicializar EmojiCompat para carregar os metadados e a face de tipos. Como a inicialização pode demorar um pouco, o processo ocorre em uma linha de execução em segundo plano.

Para inicializar EmojiCompat com a configuração de fonte disponível para download, siga estas etapas:

  1. Crie uma instância da classe FontRequest e forneça a autoridade do provedor de fonte, o pacote de provedor de fonte, a consulta de fonte e uma lista de conjuntos de hashes para o certificado. Para mais informações sobre FontRequest, consulte a seção Usar o "Fontes para download" de forma programática na documentação Fontes para download.
  2. Crie uma instância de FontRequestEmojiCompatConfig e forneça instâncias de Context e FontRequest.
  3. Inicialize EmojiCompat chamando o método init() e passe a instância de FontRequestEmojiCompatConfig.
  4. Kotlin

        class MyApplication : Application() {
    
            override fun onCreate() {
                super.onCreate()
                val fontRequest = FontRequest(
                        "com.example.fontprovider",
                        "com.example",
                        "emoji compat Font Query",
                        CERTIFICATES
                )
                val config = FontRequestEmojiCompatConfig(this, fontRequest)
                EmojiCompat.init(config)
            }
        }
        

    Java

        public class MyApplication extends Application {
          @Override
           public void onCreate() {
             super.onCreate();
             FontRequest fontRequest = new FontRequest(
               "com.example.fontprovider",
               "com.example",
               "emoji compat Font Query",
               CERTIFICATES);
             EmojiCompat.Config config = new FontRequestEmojiCompatConfig(this, fontRequest);
             EmojiCompat.init(config);
           }
        }
        
  5. Use widgets EmojiCompat nos XMLs de layout. Se você estiver usando AppCompat, consulte a seção Usar widgets da EmojiCompat com AppCompat.
  6.     <android.support.text.emoji.widget.EmojiTextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>
    
        <android.support.text.emoji.widget.EmojiEditText
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>
    
        <android.support.text.emoji.widget.EmojiButton
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>
        

Para mais informações sobre como definir EmojiCompat com a configuração de fonte disponível para download, acesse a amostra de app Emoji Compatibility (em inglês) Java | Kotlin.

Componentes da biblioteca

Componentes da biblioteca no processo da EmojiCompat
Figura 3. Componentes da biblioteca no processo da EmojiCompat.
Widgets: EmojiEditText, EmojiTextView e EmojiButton
As implementações padrão de widget para usar EmojiCompat com TextView, EditText e Button.
EmojiCompat
Superfície pública principal da Biblioteca de Suporte. Realiza todas as chamadas externas e é coordenada com as outras partes do sistema.
EmojiCompat.Config
Configura a instância singleton a ser criada.
EmojiSpan
Uma subclasse ReplacementSpan que substitui o caractere (sequências) e renderiza o glifo.
Fonte EmojiCompat
EmojiCompat usa uma fonte para exibir emojis. Essa fonte é uma versão modificada da fonte de emojis para Android. A fonte é modificada da seguinte forma:
  • Para oferecer compatibilidade com versões anteriores para renderizar emojis, todos os caracteres de emojis são representados por um único ponto de código Unicode na Área A de Uso Privado Suplementar do Unicode que começa com U+F0001.
  • Outros metadados de emojis são inseridos em um formato binário na fonte e são analisados durante a execução por EmojiCompat. Os dados são incorporados na tabela meta da fonte, com a tag particular Emji.

Opções de configuração

Você pode usar a instância EmojiCompat para modificar o comportamento de EmojiCompat. Use os seguintes métodos da classe básica para definir a configuração:

Kotlin

    val config = FontRequestEmojiCompatConfig(...)
            .setReplaceAll(true)
            .setEmojiSpanIndicatorEnabled(true)
            .setEmojiSpanIndicatorColor(Color.GREEN)
            .registerInitCallback(object: EmojiCompat.InitCallback() {
                ...
            })
    

Java

    EmojiCompat.Config config = new FontRequestEmojiCompatConfig(...)
           .setReplaceAll(true)
           .setEmojiSpanIndicatorEnabled(true)
           .setEmojiSpanIndicatorColor(Color.GREEN)
           .registerInitCallback(new InitCallback() {...})

    

Adicionar listeners de inicialização

As classes EmojiCompat e EmojiCompat fornecem métodos registerInitCallback() e unregisterInitCallback() para registrar um callback de inicialização. Para usar esses métodos, crie uma instância da classe EmojiCompat.InitCallback. Chame esses métodos e passe a instância da classe EmojiCompat.InitCallback. Quando a inicialização da Biblioteca de Suporte EmojiCompat for concluída, a classe EmojiCompat chamará o método onInitialized(). Se a biblioteca não for inicializada, a classe EmojiCompat chamará o método onFailed().

Para verificar o estado de inicialização a qualquer momento, chame o método getLoadState(). Ele retorna um dos seguintes valores: LOAD_STATE_LOADING, LOAD_STATE_SUCCEEDED ou LOAD_STATE_FAILED.

Usar a EmojiCompat com widgets da AppCompat

Caso esteja usando AppCompat widgets, é possível usar widgets EmojiCompat que se estendam de .

  1. Adicione a Biblioteca de Suporte à seção de dependências.
  2.     dependencies {
              implementation "com.android.support:support-emoji-appcompat:$version"
        }
        
  3. Use widgets AppCompat Widget da EmojiCompat em XMLs de layout.
  4.     <android.support.text.emoji.widget.EmojiAppCompatTextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>
    
        <android.support.text.emoji.widget.EmojiAppCompatEditText
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>
    
        <android.support.text.emoji.widget.EmojiAppCompatButton
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>
        

Configuração de fontes agrupadas

A Biblioteca de Suporte EmojiCompat também está disponível em uma versão de fontes agrupadas. Esse pacote inclui a fonte com os metadados incorporados. O pacote também inclui um BundledEmojiCompatConfig que usa o AssetManager para carregar os metadados e as fontes.

Observação: o tamanho da fonte é em vários megabytes.

Adicionar dependência da Biblioteca de Suporte

Para usar a Biblioteca de Suporte EmojiCompat com a configuração de fontes agrupadas, é necessário modificar as dependências do caminho de classe do projeto do seu app no ambiente de desenvolvimento.

Para adicionar uma Biblioteca de Suporte ao projeto do aplicativo:

  1. Abra o arquivo build.gradle do aplicativo.
  2. Adicione a Biblioteca de Suporte à seção dependencies.
    dependencies {
        ...
        implementation "com.android.support:support-emoji-bundled:$version"
    }
    

Usar fontes agrupadas para configurar a EmojiCompat

Para usar fontes agrupadas na configuração de EmojiCompat, siga as seguintes etapas:

  1. Use BundledEmojiCompatConfig para criar uma instância de EmojiCompat e forneça uma instância de Context.
  2. Chame o método init() para inicializar EmojiCompat e passe a instância de BundledEmojiCompatConfig.

Kotlin

    class MyApplication : Application() {

        override fun onCreate() {
            super.onCreate()
            val config = BundledEmojiCompatConfig(this)
            EmojiCompat.init(config)
        }
    }
    

Java

    public class MyApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
            EmojiCompat.init(config);
            ...
        }
    }
    

Usar a EmojiCompat sem widgets

A EmojiCompat usa EmojiSpan para renderizar imagens corretas. Portanto, ela precisa converter qualquer CharSequence informada em instâncias Spanned com EmojiSpans. A classe EmojiCompat oferece um método para converter CharSequences em instâncias Spanned com EmojiSpans. Usando esse método, é possível processar e armazenar em cache as instâncias processadas em vez da string bruta, o que melhora o desempenho do aplicativo.

Kotlin

    val processed = EmojiCompat.get().process("neutral face \uD83D\uDE10")
    

Java

    CharSequence processed = EmojiCompat.get().process("neutral face \uD83D\uDE10");
    

Usar a EmojiCompat para Editores de métodos de entrada (IMEs, na sigla em inglês)

Usando a Biblioteca de Suporte EmojiCompat, os teclados podem renderizar os emojis compatíveis com o aplicativo com que estão interagindo. Os IMEs podem usar o método hasEmojiGlyph() para verificar se EmojiCompat é capaz de renderizar um emoji. Esse método usa uma CharSequence de um emoji e retornará true se EmojiCompat puder detectar e renderizar o emoji.

O teclado também pode verificar a versão da Biblioteca de Suporte EmojiCompat compatível com o app para determinar qual emoji renderizar na paleta. Para verificar a versão, se disponível, o teclado precisa verificar se as seguintes chaves existem no pacote EditorInfo.extras:

Depois de receber as chaves no pacote EditorInfo.extras, o teclado pode usar o método hasEmojiGlyph(), em que metadataVersion é o valor de EDITOR_INFO_METAVERSION_KEY, para verificar se o app pode renderizar um emoji específico.

Usar a EmojiCompat com widgets personalizados

Você sempre pode usar o método process() para processar CharSequence previamente no seu app e adicioná-lo a qualquer widget que possa renderizar instâncias Spanned. Por exemplo, TextView. Além disso, EmojiCompat oferece as classes auxiliares de widget a seguir para permitir que você aprimore seus widgets personalizados por meio da compatibilidade com emojis, com esforço mínimo.

Amostra de TextView

Kotlin

    class MyTextView(context: Context) : AppCompatTextView(context) {

        private val emojiTextViewHelper: EmojiTextViewHelper by lazy(LazyThreadSafetyMode.NONE) {
            EmojiTextViewHelper(this).apply {
                updateTransformationMethod()
            }
        }

        override fun setFilters(filters: Array<InputFilter>) {
            super.setFilters(emojiTextViewHelper.getFilters(filters))
        }

        override fun setAllCaps(allCaps: Boolean) {
            super.setAllCaps(allCaps)
            emojiTextViewHelper.setAllCaps(allCaps)
        }
    }
    

Java

    public class MyTextView extends AppCompatTextView {
       ...
       public MyTextView(Context context) {
           super(context);
           init();
       }
       ...
       private void init() {
           getEmojiTextViewHelper().updateTransformationMethod();
       }

       @Override
       public void setFilters(InputFilter[] filters) {
           super.setFilters(getEmojiTextViewHelper().getFilters(filters));
       }

       @Override
       public void setAllCaps(boolean allCaps) {
           super.setAllCaps(allCaps);
           getEmojiTextViewHelper().setAllCaps(allCaps);
       }

       private EmojiTextViewHelper getEmojiTextViewHelper() {
           ...
       }
    }
    
Amostra de EditText

Kotlin

    class MyEditText(context: Context) : AppCompatEditText(context) {

        private val emojiEditTextHelper: EmojiEditTextHelper by lazy(LazyThreadSafetyMode.NONE) {
            EmojiEditTextHelper(this).also {
                super.setKeyListener(it.getKeyListener(keyListener))
            }
        }

        override fun setKeyListener(input: KeyListener?) {
            input?.also {
                super.setKeyListener(emojiEditTextHelper.getKeyListener(it))
            }
        }

        override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
            val inputConnection: InputConnection = super.onCreateInputConnection(outAttrs)
            return emojiEditTextHelper.onCreateInputConnection(
                    inputConnection,
                    outAttrs
            ) as InputConnection
        }
    }
    

Java

    public class MyEditText extends AppCompatEditText {
       ...
       public MyEditText(Context context) {
           super(context);
           init();
       }
       ...
       private void init() {
           super.setKeyListener(getEmojiEditTextHelper().getKeyListener(getKeyListener()));
       }

       @Override
       public void setKeyListener(android.text.method.KeyListener keyListener) {
           super.setKeyListener(getEmojiEditTextHelper().getKeyListener(keyListener));
       }

       @Override
       public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
           InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
           return getEmojiEditTextHelper().onCreateInputConnection(inputConnection, outAttrs);
       }

       private EmojiEditTextHelper getEmojiEditTextHelper() {
           ...
       }
    }
    

Perguntas frequentes

  • Como iniciar o download de fontes?
  • O download de fontes de emoji é realizado na primeira solicitação, caso elas não existam no dispositivo. A programação de downloads é transparente para o app.

  • Quanto tempo a inicialização leva?
  • Depois do download da fonte, a inicialização da EmojiCompat leva cerca de 150 milésimos de segundo.

  • Quanto de memória a Biblioteca de Suporte EmojiCompat consome?
  • Atualmente, a estrutura de dados para encontrar o emoji é carregada na memória do app e consome cerca de 200 KB.

  • Posso usar a EmojiCompat para um TextView personalizado?
  • Sim. A EmojiCompat oferece classes auxiliares para widgets personalizados. Também é possível processar uma determinada string previamente e convertê-la em Spanned. Para mais informações sobre classes auxiliares de widget, consulte a seção Usar a EmojiCompat com widgets personalizados.

  • O que acontecerá se eu adicionar widgets em XMLs de layout em dispositivos com o Android 4.4 (API nível 19) ou versões anteriores?
  • Você pode incluir a Biblioteca de Suporte EmojiCompat ou os widgets dela nos aplicativos compatíveis com os dispositivos com o Android 4.4 (API nível 19) ou versões anteriores. No entanto, se um dispositivo usar uma versão do Android anterior à API nível 19, a EmojiCompat e os widgets relacionados ficarão em um estado “sem operação”. Isso significa que o EmojiTextView se comporta exatamente como uma instância TextView. EmojiCompat comum, ou seja, ele entra imediatamente no estado LOAD_STATE_SUCCEEDED quando você chama o método init().

Outros recursos

Para mais informações sobre como usar a biblioteca EmojiCompat, assista EmojiCompat (em inglês).