AccessibilityService経由でハードキーの入力を取得する
2021/02/05
Android
ハードウェアキー
AccessibilityService
Androidアプリ開発において、ServiceなどのActivity以外でハードウェアキーの入力を取得する方法のひとつです。
ここで解説するAccessibilityService経由の方法はユーザにユーザー補助サービスの有効化をしてもらわないといけないので、いつでも使える方法ではないことに留意が必要です。
環境
- compileSdkVersion 29
- minSdkVersion 21
ユーザ補助サービス
Androidには通常のアプリ操作とは違う操作を可能にする、ユーザ補助サービスを独自に実装するための仕組みが提供されています。ですので、あくまで通常のアプリ操作の代替操作としてハードウェアキーを利用する場合にこの方法を利用すべきです。
AccessibilityServiceの実装
AccessibilityService
を継承したServiceを実装します。
AccessibilityService.onKeyEvent
をoverrideすることでハードウェアキーの入力を検出できます。
他で稼働しているServiceで使いたい場合はLocalBroadcastManagerなどでコンポーネント間通信を実装すると良いでしょう。
class AccessibilityKeyDetectionService : AccessibilityService(){
companion object{
private const val TAG: String = "KeyDetectionServ"
}
override fun onKeyEvent(event: KeyEvent?): Boolean {
Log.d(TAG, "EventKeycode: ${event?.keyCode}")
if(event?.action == KeyEvent.ACTION_DOWN){
if(event.keyCode == KeyEvent.KEYCODE_VOLUME_UP || event.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
// ボリュームキーが押された
}
}
return super.onKeyEvent(event)
}
override fun onServiceConnected() {
// nop
}
override fun onInterrupt() {
// nop
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
// nop
}
}
AccessibilityServiceの設定情報の記述
res/xml
以下にxmlリソースファイルを作成します。ルートタグはaccessibility-service
です。
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:settingsActivity=""
android:packageNames="com.hassakulab.xxx"
android:canRequestFilterKeyEvents="true"
android:description="@string/accessibility_service_description"
/>
ここの設定情報はAccessibilityService.onServiceConnected
でランタイムに設定することも可能です。
Manifestへの記述
AndroidManifest.xml
にserviceを記載します。meta-data
タグのandroid:resource
属性に上記のxmlを指定します。
<application>
<!-->中略<-->
<service android:name=".AccessibilityKeyDetectionService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="@string/accessibnility_service_label">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="@xml/accessibility_key_detection_service"
/>
</service>
</application>