晴れ、時々Android。

クレヨンしんちゃんが人生のマニュアルなヘヴィロック系ひよっこAndroidエンジニアのブログ

【Android 8.0】TextInputLayoutをフォーカスするとNullPointerExceptionでクラッシュする現象への対応

しゅっぱつおしんこ〜。しんちゃんだz(ry

文字入力欄などで、Hint表示やバリデーションエラーメッセージなどを表示するのにTextInputLayoutを使うことがしばしばありますよね。

今回は、これを使って実装していた時に特定OSで起きていた問題に対してのアプローチを書いていこうと思います。

起きていた不具合

TextInputLayoutで作った入力欄をフォーカスすると、以下のNullPointerExceptionを吐いてクラッシュすることがある

レイアウトはこんな感じ

<android.support.design.widget.TextInputLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:hintAnimationEnabled="true"
    app:hintEnabled="true"
    app:errorEnabled="false">

    <android.support.design.widget.TextInputEditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="プレースホルダーかつヒントだよ" />

</android.support.design.widget.TextInputLayout>

スタックトレース

java.lang.NullPointerException: 
  at android.app.assist.AssistStructure$WindowNode.<init> (AssistStructure.java:484)
  at android.app.assist.AssistStructure.<init> (AssistStructure.java:1908)
  at android.app.ActivityThread.handleRequestAssistContextExtras (ActivityThread.java:3056)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1820)
  at android.os.Handler.dispatchMessage (Handler.java:105)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:6592)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:240)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:769)

不具合が起こった条件

  • Android 8.0.
    • 8.1以降は発生しない
  • Android8.0から実装されたAutofillが有効になっている。
  • 動的にsetText()でテキストがセットされたTextInputLayoutをフォーカスする

解決法

その1

hintを挿入する位置を TextInputEditText -> TextInputLayout に入れ替える

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="ヒントはここに書くよ"
    app:hintAnimationEnabled="true"
    app:hintEnabled="true"
    app:errorEnabled="false">

    <android.support.design.widget.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</android.support.design.widget.TextInputLayout>

その2

TextInputEditTextに以下の属性を追加する。

android:importantForAutofill="noExcludeDescendants"

原因

調べてみると、公式でも共有されている8.0特有のバグだそう↓ https://issuetracker.google.com/issues/62834931

内容を追ってみると、

  • 8.0のプレビューでこのバグは把握されていた
  • 正式版リリースで直したつもりだったけど直ってなかった!
  • 8.1で直したよ!

    The issue is fixed on Android 8.1.

ということで、8.0にのみ残るバグとなってしまったみたい。かなしみ・・・。

まとめ

  • hintはTextInputEditTextではなく、親のTextInputLayoutに書こう!
  • それかTextInputEditTextにandroid:importantForAutofill="noExcludeDescendants"を追加したらいいよ!
  • Googleもこのバグは把握していて、8.1で直したって言ってるよ!

おわりに

色んなアプリでこのような入力欄を作ることはたくさんあると思うし、8.0ももちろんサポートすることになるからこの問題は避けて通れないなぁ・・・

皆さん気をつけましょう・・・!!

じゃ、そゆことで〜