2025/06/06 11:29 How to (actually) send DTMF on Android without being the default call app

ロボ子、今回のITニュースはAndroidアプリでDTMF信号を送信する機能の実装についてじゃ。

DTMF信号ですか。電話のプッシュ音のことですね。

そうじゃ。LifeCompanionというデジタルアシスタントに、Androidスマホとの連携機能を追加するプロジェクトで、DTMF送信機能が既存の通話プラグインに無かったからの。

なるほど。でも、Androidの公式APIでは、デフォルトの通話アプリとして登録しないとDTMF送信ができないんですね。

`android.telecom.Call`クラスの`playDtmfTone()`メソッドを使うには、`android.telecom.InCallService`を拡張して、デフォルトの通話アプリになる必要があるからの。これはちょっと大変じゃ。

それで、どうしたんですか?

そこで、Accessibility Serviceの登場じゃ!画面上のキーパッドボタンをエミュレートするという荒技に出たぞ。

Accessibility Serviceですか。画面のコンテンツ変化やViewのクリックをトリガーに動作する機能ですね。

その通り!`DTMFAccessibilityService`というシングルトンを実装して、通話アプリのパッケージ名をリスト化し、`onAccessibilityEvent()`で通話画面を監視するのじゃ。

`isInCallScreen()`で通話画面かどうかを判定して、`openDialPadIfNeeded()`でキーパッドを開き、`pressKeyDigit()`でDTMFに対応するボタンをクリックするんですね。

さすがロボ子、理解が早い!BFS(幅優先探索)でキーパッドボタンを探すのがミソじゃ。

`CallService`から`DTMFAccessibilityService`の`pressKeypadButton()`を呼び出してDTMFを送信するんですね。でも、Accessibility Serviceの権限をユーザーに要求する必要がありますね。

そうじゃな。そして、キーパッドボタンの国際化対応や通話アプリ名の検出、キーパッド要素の可視性検出など、改善点もいくつかあるぞ。

標準APIがないから、Accessibility Serviceを利用してDTMF送信をエミュレートするのは、確かに複雑ですが、有効な解決策ですね。

じゃろ?しかし、Accessibility Serviceを悪用して、画面上の情報を盗み取る輩もいるから、注意が必要じゃぞ!

そうですね。セキュリティには常に気を配る必要がありますね。

ところでロボ子、Accessibility Serviceを使って、私の部屋の掃除を自動化できないかの?

それはちょっと難しいかもしれませんね。まずは博士の研究室の整理整頓から始めましょうか?

むむ、それは耳が痛い…!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。