AndroidでUSB機器パーミッションダイアログを消す

# サマリー

# Android上でUSB機器を使うには

今発売されている多くのAndroidスマートフォンでは、
スマホ自身がホストとして、接続されたUSB機器を操作することができます。

USB式のイヤホンとかもAndroidがホストで信号＝音を送って再生しているような形です。
（たぶん、詳しい方、補足お願いします。）

他にもUSB機器としてセンサであったり、ICリーダなども接続できます。
これらはOTGケーブルを使ってスマホと繋ぐことで、スマホ側をホストとして操作できるようになります。
OTGケーブルの例：https://www.amazon.co.jp/dp/B0BYRKFH97/

## 使用したデバイス
今回の記事ではSonyのICカードリーダ「PaSoRi RC-S380」をAndroidスマホに繋いで、
アプリでICカードの情報を取得する時の経験をもとに記載します。

他のUSBデバイスを使った場合でも同じように設定可能だと思いますので、
ぜひ参考にしてください。

# AndroidアプリでUSB機器を使うとき

アプリから接続したUSB機器を操作しようとすると、
以下の画像のように、USBを使っていいかというダイアログが出てきます。
![スクリーンショット 2023-09-01 16.43.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492608/f7db1e7d-2efe-8521-7c4b-03d157a4e144.png)

このダイアログで「OK」を押せばUSB機器を使うことができます。

これで使えるようにしたら、一回数分間アプリを使って処理が終わり、
そこまで使う頻度もないなっていう時はこの対応で問題ありません。

## では何が問題？

せっかく作ったアプリで使うのは一回きりというものも少ないと思います。

ではこのアプリを繰り返し使う時どうなるか、アプリを閉じて、開いてを繰り返し使うような、
一般的な使い方をすると、、、

アプリ起動時に「毎回」ダイヤログが表示されます。
また、アプリを開いている最中でも、USB機器を「抜き差し」すると毎回ダイアログが表示されます。

つまり、**非常にうっとおしいダイアログ**になるのです。

加えて、電源線と信号線の２本の線があるOTGケーブルを使って、
スマホを充電しながらUSB機器を使うとき、

電源側の線を抜いたり、電源が不安定な状態（モバイルバッテリーでの給電など）でも
ダイアログが表示されます。
（ひどい時は「OK」を押しても1秒後にまたダイアログが出たり）

## 実現したいこと
このUSBのパーミッションダイアログ表示をなくす（厳密には一回許可したら、あとは自動で許可してくれる）ようにしたい。

# 解決方法
## 大まかな流れ
1. 接続したいUSBデバイスのベンダーIDとプロダクトIDを取得する
1. `intent-filter`でUSBが接続されたときの動作を設定する。
1. 合わせて、対象とするUSBデバイスを設定する。

## 詳しい流れ
### USBデバイスのベンダーIDとプロダクトIDを取得
#### Windowsの場合
https://kb.synology.com/ja-jp/DSM/tutorial/How_do_I_check_the_PID_VID_of_my_USB_device

1. USBデバイスを接続して、デバイスマネジャーを開く。

1. 接続したUSBデバイスを見つけて、右クリック＞プロパティ

1. プロパティを開いたら、上部のタブから「詳細」を選択

1. プロパティ（P）を「ハードウェアID」にする
    ![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492608/b47dcf2c-7348-5e2a-a2ca-1d937add7839.png)

1. 値(V)のところに表示されたもののうち、

    - 「VID_XXXX」のXXXXがベンダーID
    - 「PID_YYYY」のYYYYがプロダクトID

#### Macの場合
1. USBデバイスを接続する

1. 画面左上「このMacについて」＞詳細情報を押す

1. 表示されたコンピュータ情報を一番下までスクロールし、「システムレポート」を押す

1. 左のタブから「USB」を選択し、表示された中から接続したUSBデバイスを探す
![スクリーンショット 2023-09-01 17.32.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492608/25b9093f-9b40-1ee0-2af1-ef697386b88a.png)

1. クリックして下の詳細情報を確認

    - 「製造元ID」がベンダーID
    - 「製造ID」がプロダクトID



### アプリ側の設定
1. Android StudioでAndroid Manifest.xmlを開く


1. Android Manifest.xmlに以下を追加


    ```xml:Android Manifest.xml
    <activity
      android:label="string/app_name"
      ...>
        <intent-filter>
          <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
        </intent-filter>
        <meta-data
          android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
          android:resource="@xml/device_filter" />
    </activity>
    ```


1. res > xml にdevice_filter.xmlを新規追加する


1. 許可をしたいUSBデバイスを設定するため、以下をdevice_filter.xmlに記述
    ```xml:device_filter.xml
    <?xml version="1.0" encoding="utf-8"?>
    
    <resources>
        <usb-device vendor-id="XXXX" product-id="YYYY" />
    </resources>
    
    ```

    - XXXXは、先の章で取得したベンダーID
    - YYYYは、先の章で取得したプロダクトID

1. APKを作成

1. スマホにUSBデバイスを接続して、アプリを起動する

1. 以下の画像のようなダイアログが表示されるので、チェックを入れて「OK」する
![スクリーンショット 2023-09-01 17.37.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492608/8eed370e-2448-ce83-ced5-d1f5c19e1697.png)

こうすることで、USBデバイスを接続したらアプリが起動してくれるし、
毎回許可をする必要もなくなります。

# まとめ
これでUSBデバイスを使ったアプリで悩まされるダイアログは省略できます。

面倒かなと思ったら意外と簡単。

# 参考
https://developer.android.com/guide/topics/connectivity/usb/host?hl=ja#using-intents