EmojiCompat を使って、Android 絵文字サポートしてみた

# EmojiCompat とは
EmojiCompat は古いAndroid OSでも最新の絵文字を表示できるようにするGoogle製のサポートライブラリです。
AndroidではOSによって対応している絵文字が異なり、対応していない絵文字がきた場合、 □ と表示されてしまいます。（tofu問題）
ですが、EmojiCompat を使うことでそれを防ぐことができます。

# EmojiCompatを使うには
* Android 4.4（API level 19）までサポート
  * 4.4 以下で使った場合は、何も起こらない<br>（Android 4.3で、EmojiTextView を使った場合、TextView として動く）
* やり方は2つ
  * Downloadable fonts
  * Bundled fonts

## Downloadable fonts
* Android 8.0 で導入された [Downloadable Fonts](https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts.html) を使い、Google Play servicesから絵文字をダウンロードする方法
* Android 8.0 もしくは、Support Library 26以上（Android 4.0までサポート）が必要
* ダウンロードすることで、APKサイズを削減できる
* 絵文字フォントをダウンロードすると、EmojiCompatを初期化するのに約150ミリ秒かかるらしい
* 絵文字がデバイス上に存在しない場合、最初の要求時に絵文字フォントがダウンロードされる

## Bundled fonts
* 絵文字が含まれたライブラリを使用する方法
* その分、APKサイズが増える（試したら、7MB増えました）

# 導入

## Dependencies
以下の記述で、EmojiTextView, EmojiEditText, EmojiButton 使えます。

```groovy:app/build.gradle
dependencies {
    implementation 'com.android.support:support-emoji:$version'
    // Android Xの場合
    implementation 'androidx.emoji:emoji:$version'
}
```

AppCompat 対応する場合は以下のように書きます。
EmojiAppCompatTextView, EmojiAppCompatEditText,　EmojiAppCompatButton 使えます。

```groovy:app/build.gradle
dependencies {
    implementation 'com.android.support:support-emoji-appcompat:$version'
    // Android Xの場合
    implementation 'androidx.emoji:emoji-appcompat:$version'
}
```

## Downloadable fonts の場合

```kotlin:App.kt
class App : Application() {
    override fun onCreate() {
        super.onCreate()

        val fontRequest = FontRequest(
                "com.google.android.gms.fonts",
                "com.google.android.gms",
                "Noto Color Emoji Compat",
                R.array.com_google_android_gms_fonts_certs)
        val config = FontRequestEmojiCompatConfig(applicationContext, fontRequest)
        EmojiCompat.init(config)
    }
}
```

## Bundled fonts の場合
Dependenciesに以下を追加

```groovy:app/build.gradle
dependencies {
    implementation 'com.android.support:support-emoji-bundled:$version'
    // Android Xの場合
    implementation 'androidx.emoji:emoji-bundled:$version'
}
```

```kotlin:App.kt
class App : Application() {
    override fun onCreate() {
        super.onCreate()

        val config = BundledEmojiCompatConfig(applicationContext)
        EmojiCompat.init(config)
    }
}
```

## 表示
AppCompat版の場合はこう書く。

```xml
<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"/>
```
あとは、`EmojiAppCompatTextView.setText(CharSequence)` のようにテキストをセットするだけ

```kotlin
val emojiTextView: TextView = findViewById(R.id.emoji_text_view)
emojiTextView.text = "\uD83D\uDE10"
```

### 通常のTextViewの場合
絵文字対応することは可能です。
Googleのサンプルコードを参照
[With regular TextViews](https://github.com/googlesamples/android-EmojiCompat/tree/master/kotlinApp#with-regular-textviews)

### カスタムしたTextViewの場合
絵文字対応することは可能です。
Googleのサンプルコードを参照
[With custom TextViews](https://github.com/googlesamples/android-EmojiCompat/tree/master/kotlinApp#with-custom-textviews)

## EmojiCompat.Config による設定
`EmojiCompat.init(Config)` する前に EmojiCompat.Config で設定を変えることができる

```kotlin
val config = FontRequestEmojiCompatConfig(applicationContext, fontRequest)
                // すべての絵文字を最新の絵文字に切り替えるか
                .setReplaceAll(true)
                // EmojiCompat よって、切り替わった絵文字に色をつける（デバック目的）
                .setEmojiSpanIndicatorEnabled(true)
                .setEmojiSpanIndicatorColor(Color.GREEN)
                // EmojiCompat初期化の状態をアプリに返す
                .registerInitCallback(object : EmojiCompat.InitCallback() {
                    override fun onInitialized() {
                        Log.i(TAG, "EmojiCompat initialized")
                    }

                    override fun onFailed(throwable: Throwable?) {
                        Log.e(TAG, "EmojiCompat initialization failed", throwable)
                    }
                })
```
絵文字を統一させるという点では、 `.setReplaceAll(true)` あったほうがよさそう。

## 追記
`EmojiTextView` や `EmojiAppCompatEditText` を使って絵文字を表示すると、絵文字が半透明になってしまいます。
これは、Material Themeのデフォルトのテキストカラーに透過が入っているためです。
なので、テキストカラーを `#FF000000` など不透明な色に変えれば直ります。

# サンプル
[emoji-sample (Github)](https://github.com/taki4227/emoji-sample)

# 参考
* [Emoji Compatibility](https://developer.android.com/guide/topics/ui/look-and-feel/emoji-compat.html)
* [Google Samples](https://github.com/googlesamples/android-EmojiCompat)