Slide 1

Slide 1 text

Compose 1.7 の TextField はPOBox Plus で日本語変換でき ない tomoya0x00 2024/11/08 DroidKaigi.collect { #13@Tokyo }

Slide 2

Slide 2 text

自己紹介 tomoya0x00 X( 旧Twitter), GitHub, Zenn Pixel 9 Pro Fold 便利

Slide 3

Slide 3 text

技術書典17 の 新刊 技術書典17 で弊社の新刊を 出しました! 無料 edge-to-edge について詳 しく書きました

Slide 4

Slide 4 text

技術書典17 の 新刊 技術書典17 で弊社の新刊を 出しました! 無料 edge-to-edge について詳 しく書きました

Slide 5

Slide 5 text

Compose 1.7 を使用していますか?

Slide 6

Slide 6 text

POBox Plus の日本語入力問題で困り ましたか?

Slide 7

Slide 7 text

Zenn の記事をご覧になりましたか? Compose 1.7 のTextField はPOBox Plus で日本語変換できない https://zenn.dev/tomoya0x00/articles/be40d5f2aa4e54

Slide 8

Slide 8 text

この問題の最新の情報を共有

Slide 9

Slide 9 text

この問題の最新の情報を共有 Addressed an issue that prevented TextField from functioning correctly when using the POBox Japanese Keyboard on certain older Sony devices. (Ia9b99, b/373743376) Compose UI 1.8.0-alpha05 に修正が取りこまれた

Slide 10

Slide 10 text

そのうち、Stable 版にも修正が取りこ まれるはず Yes, this fix is planned to be included in a future 1.7.x release.

Slide 11

Slide 11 text

今回お話しすること

Slide 12

Slide 12 text

時系列でどのようにこの問題に対処し たかをお話しします もしかしたら、似たような問題に立ち向かうときに参考になるかも 最終的な回避方法は同タイトルのZenn の記事と同じです https://zenn.dev/tomoya0x00/articles/be40d5f2aa4e54

Slide 13

Slide 13 text

ある金曜日の夕方…

Slide 14

Slide 14 text

" 正常に文字入力できない" という問 合せが急増

Slide 15

Slide 15 text

" 正常に文字入力できない" という問 合せが急増 Compose 1.7 にした最新版アプリを100% 配信にして、3 日ほど経過してい た 漢字変換ができず、濁点や半濁点なども打てない トグル入力が出来ない 『あ』を三回押すと『う』ではなく『あああ』になってしまう 現象報告があるのXperia 端末のみ ただし、新しめのXperia 端末では報告無し

Slide 16

Slide 16 text

hotfix 対応が必要

Slide 17

Slide 17 text

Xperia 端末でしか起きないのなら、 Xperia プリインIME との組み合わせで 発生する問題かも?

Slide 18

Slide 18 text

Xperia プリインのIME

Slide 19

Slide 19 text

POBox Plus 2019 年頃までのXperia にプ リインされていたIME 慣れ親しんだPOBox Plus を 新しいXperia に手動でイン ストールしてご利用されてい るケースもある

Slide 20

Slide 20 text

これまでに得た情報で原因を推測 Compose1.6 のアプリでは日本語入力の問題は発生していなかった 少なくとも、大きな問題になるほどの問合せは発生していない Compose1.7 にしたアプリを100% 配信にしてから、お問い合わせが急増し ている つまり、Compose1.7 + POBox Plus の組み合わせで日本語入力に問題が発生 している

Slide 21

Slide 21 text

Compose1.7.2 から1.7.3 へのアップデ ートでなおる可能性もありそう Fixed exception thrown when the IME is active on an external View and the Next action is used to enter focus on the ComposeView. The clearFocus() behavior aligns with View behavior on API < 28, where clearFocus() can cause the default View to be focused. 意外と簡単に修正できるかも?(フラグ)

Slide 22

Slide 22 text

何はともあれ、まずは問題が再現す る環境の確保が必要

Slide 23

Slide 23 text

たまたま、お義母さんから頂いた古 い端末が、Xperia 端末(Android 5.0 ) でPOBox Plus もプリインされていた

Slide 24

Slide 24 text

原因の推測が正しいかの検証 Compose1.7 なアプリでは現象が再現した Compose1.6 なアプリでは再現せず なので、Compose 1.7 から発生している問題である事が確定

Slide 25

Slide 25 text

どうやってhotfix 対応するのか?

Slide 26

Slide 26 text

どうやってhotfix 対応するのか? Compoes1.7.3 で修正されているか試す Compose1.7.x のまま、問題を回避できる方法を探す Compose1.6 に戻す

Slide 27

Slide 27 text

Compoes1.7.3 で修正されているか試 す

Slide 28

Slide 28 text

Compoes1.7.3 で修正されているか試 す:効果無し

Slide 29

Slide 29 text

Compose1.7.x のまま、問題を回避で きる方法を探す

Slide 30

Slide 30 text

Compose1.7.x のまま、問題を回避で きる方法を探す Compose のTextField を単純にAndroid View のEditText に置き換えると、問 題を回避できる事は確認できた 素のEditText のままで試したので、デザインは適用作業は必要 日本語入力をサポートしているComposable は3 箇所なので、EditText 化す る箇所はそんなに多くない

Slide 31

Slide 31 text

久々にレイアウトXML などを触って Compose 版と同様なデザイン・挙動 をEditText 版で実現

Slide 32

Slide 32 text

日本語入力対応のTextField をEditText に置き換えてhotfix 対応完了

Slide 33

Slide 33 text

日本語入力対応のTextField をEditText に置き換えてhotfix 対応完了

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

突然のANR EditText のタップでANR 発生する画面での再現率 100% LazyList で多数のアイテムを 表示している画面で発生

Slide 36

Slide 36 text

なぜANR が発生するのか? アプリ側のコードが何回も実行されて起きているわけでは無さそう 無駄なRecomposition が大量に発生しているわけでは無さそう

Slide 37

Slide 37 text

もしかして、Compose1.7 の不具 合… ?

Slide 38

Slide 38 text

ANR in focus search with Compose 1.7.2 Priority: P4 のまま進捗無し https://issuetracker.google.com/issues/369354336

Slide 39

Slide 39 text

hotfix 対応としてEditText 化+ANR 問題 回避は厳しい…

Slide 40

Slide 40 text

泣く泣くCompose1.6 に戻してhotfix 対応としてリリース ripple やnavigation 周りの変更があるため、400 行超えの変更をrevert

Slide 41

Slide 41 text

hotfix 対応を乗り越えて、週明け

Slide 42

Slide 42 text

改めて状況整理 Compose1.7 のTextField はPOBox Plus で日本語変換できない Compose1.7 でEdiText を表示してタップするとANR が起きる hotfix 対応としてCompose .6 に戻した

Slide 43

Slide 43 text

どうにかしてCompose1.7 を使いたい Compose1.7 ではCompose のクラッシュ不具合がかなり修正されている Compose1.6 を今後も使い続けるのは厳しい Compose のアップデートに取り残されてしまう

Slide 44

Slide 44 text

基本方針 Google に問題を報告 Google Issue Tracker に登録する Compose1.7 のままワークアラウンド対応を入れてPOBox Plus での日本語 変換を動かす Compose1.7 側の修正に時間がかかる可能性があるため

Slide 45

Slide 45 text

基本方針 Google に問題を報告 Google Issue Tracker に登録する Compose1.7 のままワークアラウンド対応を入れてPOBox Plus での日本語 変換を動かす Compose1.7 側の修正に時間がかかる可能性があるため

Slide 46

Slide 46 text

Google に問題を報告 TextField で日本語変換できない https://issuetracker.google.com/issues/373743376 @yuyuyuyuyuri さんに対応して貰った(再現アプリは簡単に作れた) EdiText タップでANR 発生 https://issuetracker.google.com/issues/369354336 Issue はすでに存在するが、再現方法がわからないからか進展が無い 弊社アプリでは再現するのでこれを元に再現アプリをつくって共有する

Slide 47

Slide 47 text

EdiText タップでANR 再現アプリ作成

Slide 48

Slide 48 text

EdiText タップでANR 再現アプリ作成 幸い、弊社のアプリでは100% 再現できる しかし、弊社アプリのソースをそのままGoogle に共有はできない ANR 発生の要素を特定して再現アプリとして別のアプリを作る必要がある

Slide 49

Slide 49 text

EdiText タップでANR 再現アプリ作成 - ANR 発生要素の特定 弊社アプリを弄ってシンプルにしていき、ANR 発生要素に当たりをつける LazyColumn でもLazyVerticalGrid でも発生する LazyList の表示アイテム数が減ると、メインスレッド占有時間は減る LazyList の表示アイテムがclickable だと、メインスレッド占有時間が増え るっぽい

Slide 50

Slide 50 text

EdiText タップでANR 再現アプリ作成 - 再現アプリの実装 EditText + LazyColumn だけでは再現せず 弊社アプリはEditText の下にButton がを配置していたので、これを再現ア プリに足したら100% 再現できるようになった Isssue Tracker でこの再現アプリを共有 優先度を上げて欲しいというお願いをした:P4 -> P1 https://github.com/tomoya0x00/nowinandroid/tree/issue_edittext_anr

Slide 51

Slide 51 text

基本方針 Google に問題を報告 Google Issue Tracker に登録する Compose1.7 のままワークアラウンド対応を入れてPOBox Plus での日本語 変換を動かす Compose1.7 側の修正に時間がかかる可能性があるため

Slide 52

Slide 52 text

Compose1.7 のままワークアラウンド 導入 EditText 化無しで問題の回避に挑戦 EditText 化ANR 問題の回避に挑戦

Slide 53

Slide 53 text

Compose1.7 のままワークアラウンド 導入 EditText 化無しで問題の回避に挑戦 EditText 化ANR 問題の回避に挑戦

Slide 54

Slide 54 text

EditText 化無しで問題の回避に挑戦 Compose1.7 からTextField の実装が変わっている BasicTextField2 がBasicTextField にリネームされている 昔のBasicTextField に実装を戻せば、問題を回避できるかもしれない Compose1.6 のTextField の実装をCompose1.7 に移植してみる

Slide 55

Slide 55 text

古いTextField を移植 40 個以上のファイルを移植 しかし、効果は無し もっと低レイヤーで発生してい る問題っぽい

Slide 56

Slide 56 text

Compose1.7 のままワークアラウンド 導入 EditText 化無しで問題の回避に挑戦 EditText 化ANR 問題の回避に挑戦

Slide 57

Slide 57 text

EditText 化ANR 問題の回避に挑戦 なぜANR が起きているのか?を解析 100% 再現できるアプリがあるので、現象を解析しやすい 解析結果を元に回避方法を探る

Slide 58

Slide 58 text

EditText 化ANR 問題の回避に挑戦 なぜANR が起きているのか?を解析 100% 再現できるアプリがあるので、現象を解析しやすい 解析結果を元に回避方法を探る

Slide 59

Slide 59 text

なぜANR が起きているのか?を解析 どこにfocus を当てるかを探していそう androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.findBestCandidate-4WY_MpI(TwoD androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.searchChildren-4C6V_qg(TwoDime androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.access$searchChildren-4C6V_qg( androidx.compose.ui.focus.TwoDimensionalFocusSearchKt$generateAndSearchChildren$1.in androidx.compose.ui.focus.TwoDimensionalFocusSearchKt$generateAndSearchChildren$1.in ~~ 省略 ~~ androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.generateAndSearchChildren-4C6V androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.twoDimensionalFocusSearch-sMXa androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.twoDimensionalFocusSearch-sMXa androidx.compose.ui.focus.FocusTraversalKt.focusSearch-0X8WOeE(FocusTraversal.kt:109 androidx.compose.ui.focus.FocusOwnerImpl.focusSearch-ULY8qGw(FocusOwnerImpl.kt:247) androidx.compose.ui.platform.AndroidComposeView.focusSearch(AndroidComposeView.andro

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

なぜANR が起きているのか?を解析 メインスレッドが常に動き続けている メモリも大量に消費し、GC が発生しまくっている 仮説:メインスレッドでfocus 先を探し続けておりANR が発生する

Slide 62

Slide 62 text

仮説の検証:メインスレッドでfocus 先を探し続けておりANR が発生する TwoDimensionalFocusSearch 内にnot suspend なbreakpoint を追加してロ グ出力 ひたすらfocus 先を探して探索処理を繰り返していることが判明 LazyList の中も展開して(現在は非表示の箇所も) 、探索している LazyList に渡すアイテム数が増えるとfocus 探索時間が増えてANR となる 最終的にはfocus 先を決定できずに諦めていそう

Slide 63

Slide 63 text

EditText 化ANR 問題の回避に挑戦 なぜANR が起きているのか?を解析 100% 再現できるアプリがあるので、現象を解析しやすい 解析結果を元に回避方法を探る

Slide 64

Slide 64 text

解析結果を元に回避方法を探る 回避案1: 手動でrequestFocus してみる focus 先をうまく探せないのなら、focus 先を指定してrequestFocus すれ ば良いのでは?

Slide 65

Slide 65 text

回避案1: 手動でrequestFocus してみる 結果はNG あくまでfocus が当たった後になぜか再度focus 先を探しにいっているの で、このアプローチではダメ EditText にfocus が当たった後、InputMethodManager 経由で再度focus 先を探しにいっている EditText の下方向に対してEditText を探しに行っているので、見つかる はずがない

Slide 66

Slide 66 text

解析結果を元に回避方法を探る 回避案1: 手動でrequestFocus してみる 回避案2: AndroidComposeView を差し替えてfocusSearch をブロックす る InputMethodManager 経由のfocus 探す処理は無駄なのでブロックした い

Slide 67

Slide 67 text

回避案2 :AndroidComposeView を差 し替えれば回避できるのでは? 以前に似たようなアプローチを他の問題で適用したことがある 新しめのFire タブレットの一部で、Compose アプリのタップ位置がずれ る https://zenn.dev/tomoya0x00/articles/e9c0558e5d8e16 結果はNG AndroidComposeView をCompose 側のソースコード変更無しに差し替える のが難しそう

Slide 68

Slide 68 text

改めて回避策について考える あくまでAndroidComposeView#focusSearch が呼ばれるのを防げば良い すでにfocus が当たったあとに無駄に次のfocus 先を探しているだけなの で、何もしなくて良い

Slide 69

Slide 69 text

解析結果を元に回避方法を探る 回避案1: 手動でrequestFocus してみる 回避案2: AndroidComposeView を差し替えてfocusSearch をブロックする 回避案3 :独自のViewGroup を間に挟んでfocusSearch をブロックする InputMethodManager 経由のfocus 探す処理は無駄なのでブロックした い

Slide 70

Slide 70 text

回避案3 :独自のViewGroup を間に挟 んでfocusSearch をブロックする EditText を独自のViewGroup で包めば、focusSearch をブロックできるので は?

Slide 71

Slide 71 text

回避案3 :独自のViewGroup を間に挟 んでfocusSearch をブロックする focusSearch でnull を返すだけ focus に問題が発生しそうですが、軽く動かした限りは問題なさそう 複数の子View が存在しなければたぶん大丈夫? class WorkaroundFocusSearchLayout : FrameLayout { // constructor は省略してます override fun focusSearch(focused: View?, direction: Int): View? { return null } }

Slide 72

Slide 72 text

これでめでたしめでたし

Slide 73

Slide 73 text

これでめでたしめでたし

Slide 74

Slide 74 text

キーボードが表示されない EditText に対してrequestFocus してもキーボードが表示されない EditText に対してはSoftwareKeyboardController#show しても何も起きない 昔ながらのInputMethodManager#showSoftInput で解決

Slide 75

Slide 75 text

今度こそめでたしめでたし

Slide 76

Slide 76 text

今度こそめでたしめでたし

Slide 77

Slide 77 text

キーボードが 隠れない Android 8.0 な端末でキーワ ード検索を実行してもキー ボードが表示されたままと なる clearFocus するとsetFocus さ れる

Slide 78

Slide 78 text

キーボードが隠れない Issue Tarcker に登録済み FocusManager.clearFocus() sets focus the first AndroidViewBinding https://issuetracker.google.com/issues/374031296 clearFocus の使用を避け、サイズが小さなSpacer にfocus を当てて代用する

Slide 79

Slide 79 text

キーボードが隠れない focus を外したいときにfocus を当てる先のSpacer を配置 Spacer は高さ・幅共に1px 以上のサイズが必要 どちらかが0px のComposable にfocus を当てるとクラッシュする val dummyFocusRequester = remember { FocusRequester() } Spacer( modifier = Modifier .fillMaxWidth() .height(1.dp) .focusRequester(dummyFocusRequester) .focusable(), )

Slide 80

Slide 80 text

キーボードが隠れない workaroundFocusManager を作る clearFocus でSpacer にrequestFocus val workaroundFocusManager: FocusManager = remember( focusManager, dummyFocusRequester, ) { object : FocusManager { override fun moveFocus(focusDirection: FocusDirection): Boolean = focusManager.moveFocus(focusDirection) override fun clearFocus(force: Boolean) { dummyFocusRequester.requestFocus() } } }

Slide 81

Slide 81 text

キーボードが隠れない workaroundFocusManager をLocalFocusManager として配る CompositionLocalProvider( LocalFocusManager provides workaroundFocusManager, ) { ... }

Slide 82

Slide 82 text

無事にEditText 化してリリース!!!

Slide 83

Slide 83 text

改めて現在の状態を共有 2024/11/08 現在、Compose1.7.x のTextField はPOBox Plus で日本語変換で きない Compose UI 1.8.0-alpha05 には修正が取りこまれた 待っていれば1.7.x 系にも修正が適用されるはず… ? Compose1.7.x でEditText を使うには様々な問題がある タップでANR 発生、キーボード表示されない、clearFocus でsetFocus

Slide 84

Slide 84 text

まとめ 一つの問題を回避しようとしたら、他の様々な問題がでてきて大変だった まずは再現できる環境をつくれると、解析できるし回避策も検討しやすい AndroidX などの問題に気付いたら、ぜひIssue Tracker に投稿を! 同じ問題で困る人が減る Compose1.7.x は他にもAndroid View 関係の問題があるかもしれないので、 十分なテストを推奨 いくつかのAndroid バージョンで動かした方が良い