2022年1月24日月曜日

【Android USB oscilloscope】(5) OTG USBのattach/detach検出

余っているAndroidスマホをオシロにしよう!

Android Studioとにらめっこしています.アニメを観たりしてお勉強が進みません.

DLしたsample codeを参考にしています.   →usb-serial-for-android
これはUSB COMの簡単なterminalアプリです.

これのFT232のデバドラ部分の動作を知りたいのですが、fragmentを多用していて読解が困難です.お勉強がてら、fragmentの無いアプリに作り替えたろかと思います.また java → kotlin への変換もやったろかと思います.

ーーーー
まずは初歩の初歩でこんなのをkotlinで動かしてみます.
 1)OTG USBにarduinoを接続する
 2)スマホがUSB挿入を認識する  →attachと表示
 3)arduinoを外すとスマホが認識する  →detachと表示

冒頭でusb-serial-for-androidを参考にしたと書きましたが、USBをattach/detachする段階ではまだusb-serial-for-androidの出番ではありませんので使いません.
どういう意味かというと、usb-serial-for-androidはFT232(COM通信)を動かすものですが、USB attach/detachの段階はandroid OSの仕事だからです.attachされたとOSが検出した後がusb-serial-for-androidの出番になります.

以下でキモの箇所を説明します.
project folderをupしておきますので詳しくは現物をご覧ください.

手順1    空のprojectをつくる
最初にandroid studioのnew projectで空のkotlin projectを作ります.

手順2    res/layout/activity_main.xmlを編集
textviewを2ヶ配置し、片方のIDをIDtxt2にしておきます.あとで文字を書き換えるため.

手順3    AndroidManufest.xmlを編集
変更するのはactivityのところ.赤字の①②です.
<activity
  android:name=".MainActivity"
  android:exported="true"
  android:launchMode="singleTask">   ①
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
    <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>

②について.前提となる知識から述べると、android OSはUSBに何かが接続されたのを検知すると、intentというメッセージをアプリに向かって発します.
当アプリは、intentのうちUSB ATTACHEDを知りたいので、OSに対して「我はUSB ATTACHEDに興味あり」と申告します.だからmanufestにその旨を記述しているんです.それが②です.

①について.当アプリはUSB ATTACHEDを知るといろいろな仕事を始めるわけですが、window画面を切り替えるのか、そうでなく同じwindow画面のままなのか、それを①は指定しているようです.window画面切り替え無しなのでsingkeTaskにしてます.もしもwindow画面切り替えありだと、別のwindow画面へintentが飛んで行ってしまってintentを受信できなくなっちゃうみたいよ.
なおandroid OSでは、window画面のことをactivityと呼びます.

「USB DETACHも知りたいのでは?」と思った人がいるでしょう.それは後で説明します.

device_filterについては後で説明します.

手順4  device_filter.xmlをコピー
話題が出たついでにここで説明します.
android OSは、接続されたUSB機器のVID/PIDをチェックするらしいです.
当アプリが対応するVID/PIDのリストがdevice_filter.xmlです.
USB COM ICは何種類もあるので、それらのVID/PIDのリストになっています.

usb-serial-for-androidは使わないと上で書きましたが、device_filter.xmlだけはusb-serial-for-androidからもらってきます.res/xml/の下に置きます.

手順5   build.gradleを編集
3つある真ん中のやつだと思いますが、赤い行を追加します.これが無いとeditorの補完が効かなくてすごく不便です.
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}

手順6   MainActivity.ktを編集
ここがキモのところです.
まずはおなじみonCreate().
①は画面表示をしてます.USB挿入待ちです.
②はあとで説明するdetach処理です.
override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(R.layout.activity_main)
   IDtxt2.text = "waiting for a USB action"    ①
   setBroadcastReceivers()    ②
}

USB attach処理について.
window画面は、生成されて消されるまでにonCreate()やonDestroy()などの関数がcallされます.そのうちの1つにonNewIntent()があります.
手順3で「USBに何かが挿入されたら教えてくれ」と申告しました.それを受けてOSはUSB挿入時にonNewIntent()をcallして教えてくれます.
intent=ATTACHEDをチェックしたうえで、表示を「attached USB COM」に切り替えます.それ以上の処理は当アプリではやりません.
override fun onNewIntent(intent : Intent) {
  if ("android.hardware.usb.action.USB_DEVICE_ATTACHED" == intent.action) {
      IDtxt2.text = "attached USB COM"
  }
  super.onNewIntent(intent)
}

このようにattach処理は簡潔に記述できるのですが、問題はdetach処理です.
detach処理は別のやり方をせにゃいけません.
その理由は、、、
 ・attach intentは、window画面へ向けて発せられる =onNewIntent()
 ・detach intentは、ブロードキャストメッセージとして発せられる =onReceive()
という違いがあるからです.うぎゃっ、めんどくせぇ

detach処理はこれです.ブロードキャストメッセージを捕まえるためにここでごにょごにょやってます.美しくないような気がする.せっかくmanufestがあるのにさ.かったるいので解説する気が失せます.
    var mUsbReceiver: BroadcastReceiver? = null
    fun setBroadcastReceivers() {
        mUsbReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent) {
                if (UsbManager.ACTION_USB_DEVICE_DETACHED == intent.action) {
                    IDtxt2.text = "detached USB COM"
                }
            }
        }
        val filter = IntentFilter()
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
        registerReceiver(mUsbReceiver , filter)
    }

これで変更箇所は全部のはずです.

ーーーー
当アプリをスマホ実機で動かしてみます.

↓スマホ上に現れるアイコン
↓起動画面
↓USBにarduinoを挿したとき
↓arduinoを抜いたとき
てな動きをします.

4へ            6へ

かしこ

0 件のコメント:

コメントを投稿