KITCHEN DRINKER

主にAndroid開発メモとか

EmojiEditTextでOS8.0でcrash時の対応

チーム内で対応したことだけど、同じこと起こる人居そうなのでメモっとく。

OS 8.0がリリースされた時からちょくちょく出てたcrashが、EmojiCompat導入した途端増えだした。

Fatal Exception: java.lang.ArrayIndexOutOfBoundsException: length=3; index=-1
       at android.text.DynamicLayout.getBlockIndex(DynamicLayout.java:646)
       at android.widget.Editor.drawHardwareAccelerated(Editor.java:1695)
       at android.widget.Editor.onDraw(Editor.java:1664)
       at android.widget.TextView.onDraw(TextView.java:6880)
       at android.view.View.draw(View.java:19132)
       at android.view.View.updateDisplayListIfDirty(View.java:18082)
…

発生条件

  • OS 8.0
  • 端末の開発者オプション設定より、GPUレンダリング設定(ハードウェアアクセラレーション)を有効にしている
  • EditTextで絵文字を含んだあるフォーマットの条件下で入力しようとする

原因

OS 8.0のみ発生するGoogle側のバグのよう

https://issuetracker.google.com/issues/67102093

対応

上記のissueにも上がっていた対応策で、OS 8.0.0の端末のみ入力画面時はGPUレンダリング設定を強制的に無効化にするようにする。

editText.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

BindingAdapterで作った。

@BindingAdapter("forceLayerTypeSoftware")
fun EditText.setForceLayerTypeSoftware(forceLayerTypeSoftware: Boolean = false) {
  if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O || forceLayerTypeSoftware) {
    setLayerType(View.LAYER_TYPE_SOFTWARE, null)
  }
}

xml

      <android.support.text.emoji.widget.EmojiEditText
    …
+          app:forceLayerTypeSoftware="@{false}"
           />

おそらくOS 8.1.0では修正されているはずなので、対象ユーザーがいなくなったら消す予定(忘れそう😇)