絵文字の互換性

EmojiCompat サポート ライブラリは、最新の絵文字で Android デバイスを最新の状態に保つことを目的としています。これにより、足りない絵文字が ☐ の形式(デバイスにテキストを表示するフォントがないことを示します)でアプリに表示されることを防ぎます。EmojiCompat サポート ライブラリを使用すると、アプリユーザーは、最新の絵文字を入手するために Android OS のアップデートを待つ必要がなくなります。

絵文字を表示しているデバイス
図 1. 絵文字の比較

以下の関連リソースもご覧ください。

  • 絵文字互換性のサンプルアプリ Java | Kotlin

EmojiCompat の仕組み

EmojiCompat サポート ライブラリには、Android 4.4(API レベル 19)以降を搭載しているデバイスで下位互換性のある絵文字サポートを実装するクラスが用意されています。EmojiCompat は、バンドルされたフォントまたはダウンロード可能なフォントで設定できます。設定の詳細については、下記のセクションをご覧ください。

EmojiCompat は、指定された CharSequence の絵文字を識別し、必要に応じて EmojiSpans に置き換え、最後に絵文字グリフをレンダリングします。図 2 にプロセスを示します。

EmojiCompat のプロセス
図 2. EmojiCompat のプロセス

ダウンロード可能なフォントの設定

ダウンロード可能なフォントの設定では、Downloadable Fonts サポート ライブラリ機能を使用して絵文字フォントをダウンロードします。また、必要な絵文字メタデータも更新されます。これは EmojiCompat サポート ライブラリが Unicode 仕様の最新バージョンに対応するために必要です。

サポート ライブラリの依存関係の追加

EmojiCompat サポート ライブラリを使用するには、開発環境内でアプリ プロジェクトのクラスパスの依存関係を変更する必要があります。

アプリのプロジェクトにサポート ライブラリを追加するには:

  1. アプリの build.gradle ファイルを開きます。
  2. サポート ライブラリを dependencies セクションに追加します。

Groovy

dependencies {
    ...
    implementation "androidx.emoji:emoji:28.0.0"
}

Kotlin

dependencies {
    ...
    implementation("androidx.emoji:emoji:28.0.0")
}

ダウンロード可能なフォントの設定の初期化

メタデータと書体を読み込むには、EmojiCompat を初期化する必要があります。初期化には時間がかかることがあるため、初期化プロセスはバックグラウンド スレッドで実行されます。

ダウンロード可能なフォントの設定で EmojiCompat を初期化する手順は次のとおりです。

  1. FontRequest クラスのインスタンスを作成し、フォント プロバイダ権限、フォント プロバイダ パッケージ、フォントクエリ、証明書のハッシュセットのリストを指定します。FontRequest の詳細については、ダウンロード可能なフォント ドキュメントのダウンロード可能なフォントをプログラムで使用するのセクションをご覧ください。
  2. FontRequestEmojiCompatConfig のインスタンスを作成し、ContextFontRequest のインスタンスを指定します。
  3. init() メソッドを呼び出して EmojiCompat を初期化し、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. レイアウト XML で EmojiCompat ウィジェットを使用します。AppCompat を使用している場合は、AppCompat での EmojiCompat ウィジェットの使用のセクションをご覧ください。
  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"/>
    

ダウンロード可能なフォントで EmojiCompat を設定する方法の詳細については、Emoji Compatibility サンプルアプリをご覧ください(Java | Kotlin)。

ライブラリ コンポーネント

EmojiCompat プロセスのライブラリ コンポーネント
図 3. EmojiCompat プロセスのライブラリ コンポーネント
ウィジェット: EmojiEditTextEmojiTextViewEmojiButton
TextViewEditTextButtonEmojiCompat を使用するデフォルトのウィジェット実装。
EmojiCompat
サポート ライブラリのメインのパブリック サーフェス。外部呼び出しをすべて実行し、システムの他の部分と連携します。
EmojiCompat.Config
作成するシングルトン インスタンスを設定します。
EmojiSpan
文字(シーケンス)を置き換えてグリフをレンダリングする ReplacementSpan サブクラス。
EmojiCompat フォント
EmojiCompat はフォントを使用して絵文字を表示します。このフォントは Android 絵文字フォントの変更版です。フォントは次のように変更されています。
  • 絵文字のレンダリングに下位互換性を持たせるために、U+F0001 で始まる Unicode の補助私用領域 A では、すべての絵文字が単一の Unicode コードポイントで表されます。
  • 追加の絵文字メタデータはバイナリ形式でフォントに挿入され、実行時に EmojiCompat によって解析されます。データはフォントの meta テーブルに埋め込まれ、Emji というプライベート タグが付けられます。

設定オプション

EmojiCompat インスタンスを使用して、EmojiCompat の動作を変更できます。基本クラスの次のメソッドを使用して、構成を設定できます。

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() {...})

初期化リスナーの追加

EmojiCompat クラスと EmojiCompat クラスは、初期化コールバックを登録するための registerInitCallback() メソッドと unregisterInitCallback() メソッドを提供します。これらのメソッドを使用するには、EmojiCompat.InitCallback クラスのインスタンスを作成します。これらのメソッドを呼び出し、EmojiCompat.InitCallback クラスのインスタンスを渡します。EmojiCompat サポート ライブラリの初期化が成功すると、EmojiCompat クラスは onInitialized() メソッドを呼び出します。EmojiCompatライブラリの初期化ができなかった場合、EmojiCompat クラスは onFailed() メソッドを呼び出します。

初期化状態を任意の時点で確認するには、getLoadState() メソッドを呼び出します。LOAD_STATE_LOADINGLOAD_STATE_SUCCEEDED、または LOAD_STATE_FAILED のいずれかの値が返されます。

AppCompat ウィジェットでの EmojiCompat の使用

AppCompat widgets を使用している場合、AppCompat widgets の拡張である EmojiCompat ウィジェットを使用できます。

  1. サポート ライブラリを dependencies セクションに追加します。

    Groovy

    dependencies {
        ...
        implementation "androidx.emoji:emoji-bundled:$version"
    }
    

    Kotlin

          dependencies {
              implementation("androidx.emoji:emoji-appcompat:$version")
          }
          

    Groovy

          dependencies {
              implementation "androidx.emoji:emoji-appcompat:$version"
          }
          
  2. レイアウト XML で EmojiCompat AppCompat Widget ウィジェットを使用します。
  3. <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"/>
    

バンドルされたフォントの設定

EmojiCompat サポート ライブラリは、バンドルされたフォントのバージョンでも利用できます。このパッケージには、メタデータが埋め込まれたフォントも含まれます。パッケージには BundledEmojiCompatConfig も含まれています。これは AssetManager を使用してメタデータとフォントを読み込みます。

注: フォントのサイズは数メガバイトあります。

サポート ライブラリの依存関係の追加

バンドルされたフォントの設定で EmojiCompat サポート ライブラリを使用するには、開発環境内でアプリ プロジェクトのクラスパスの依存関係を変更する必要があります

アプリのプロジェクトにサポート ライブラリを追加するには:

  1. アプリの build.gradle ファイルを開きます。
  2. サポート ライブラリを dependencies セクションに追加します。

Groovy

dependencies {
    ...
    implementation "androidx.emoji:emoji:28.0.0"
}

Kotlin

dependencies {
    ...
    implementation("androidx.emoji:emoji:28.0.0")
}

バンドルされたフォントを使用した EmojiCompat の設定

バンドルされたフォントを使用して EmojiCompat を設定する手順は次のとおりです。

  1. BundledEmojiCompatConfig を使用して EmojiCompat のインスタンスを作成し、Context のインスタンスを指定します。
  2. init() メソッドを呼び出して EmojiCompat を初期化し、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);
        ...
    }
}

ウィジェットなしでの EmojiCompat の使用

EmojiCompat は、EmojiSpan を使用して正しい画像をレンダリングします。そのため、EmojiSpans で所定の CharSequenceSpanned インスタンスに変換する必要があります。EmojiCompat クラスは、EmojiSpansCharSequencesSpanned に変換するためのメソッドを提供します。このメソッドを使用すると、生の文字列ではなく処理されたインスタンスの処理とキャッシュができるため、アプリのパフォーマンスが向上します。

Kotlin

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

Java

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

IME に EmojiCompat を使用する

EmojiCompat サポート ライブラリを使用すると、キーボードによって、操作対象のアプリでサポートされている絵文字をレンダリングできます。IME は hasEmojiGlyph() メソッドを使用して、EmojiCompat が絵文字をレンダリングできるかどうかを確認できます。このメソッドは絵文字の CharSequence を取り、EmojiCompat が絵文字を検出しレンダリングできる場合に true を返します。

またキーボードは、アプリがサポートしている EmojiCompat サポート ライブラリのバージョンを確認して、パレットでレンダリングする絵文字を決定することもできます。バージョンを確認するには、利用可能な場合、キーボードは EditorInfo.extras バンドルに次のキーがあるかどうかを確認する必要があります。

EditorInfo.extras バンドルのキーを受け取ると、キーボードは hasEmojiGlyph() をメソッドを使用できます。metadataVersionEDITOR_INFO_METAVERSION_KEY の値で、アプリが特定の絵文字をレンダリングできるかどうかを確認します。

カスタム ウィジェットでの EmojiCompat の使用

いつでも process() メソッドを使用してアプリで CharSequence を前処理し、Spanned インスタンスをレンダリングできる任意のウィジェットに追加できます(例: TextView)。さらに、EmojiCompat には次のウィジェット ヘルパークラスが用意されており、カスタム ウィジェットを絵文字サポートで簡単に充実させられます。

サンプル 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() {
       ...
   }
}
サンプル 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() {
       ...
   }
}

よくある質問

  • フォントのダウンロードを開始するにはどうすればよいですか。
  • 絵文字フォントは、デバイスに存在しない場合、最初のリクエストでダウンロードされます。ダウンロードのスケジュールは、アプリに対して透明です。

  • 初期化にはどのくらいの時間がかかりますか。
  • フォントのダウンロード後、EmojiCompat の初期化に約 150 ミリ秒かかります。

  • EmojiCompat サポート ライブラリのメモリ使用量はどのくらいですか。
  • 現在、絵文字を検出するデータ構造はアプリのメモリに読み込まれ、約 200 KB を使用します。

  • EmojiCompat をカスタム TextView に使用できますか。
  • はい。EmojiCompat は、カスタム ウィジェットのヘルパークラスを提供します。また、所定の文字列を前処理し、Spanned に変換することもできます。ウィジェット ヘルパークラスの詳細については、カスタム ウィジェットでの EmojiCompat の使用のセクションをご覧ください。

  • Android 4.4(API レベル 19)以前を搭載しているデバイスでレイアウト XML にウィジェットを追加するとどうなりますか。
  • Android 4.4(API レベル 19)以前を搭載しているデバイスをサポートするアプリには、EmojiCompat サポート ライブラリまたはそのウィジェットを追加できます。ただし、デバイスが API レベル 19 より前の Android バージョンを搭載している場合、EmojiCompat とそのウィジェットは「オペレーションなし」の状態になります。つまり、EmojiTextView は通常の TextView とまったく同じように動作します。EmojiCompat インスタンスは、init() を呼び出すとすぐに LOAD_STATE_SUCCEEDED 状態になります。

参考情報

EmojiCompat ライブラリの使用方法については、EmojiCompat をご覧ください。