GitHubに公開したAndroidアプリ「BleSwitch」について(技術解説)

撮影タイミングは実機テストに使った端末に合わせて調整しています。

Android9.x(実機はGalaxyJ6+)ではLOW_LATENCYモードで100ms毎スキャンします。
それ以外のバージョンではLOW_ENERGYモードで起動します。2000msでスキャン3000ms休止のくり返しになります。実機ではスキャンできなかったり一回のボタン操作にもかかわらず2回以上信号を受けてスマホアプリを起動してしまうことがありました。

GitHubに公開したAndroidアプリ「BleSwitch」について(使い方)
ここに、こう書いていますが、少し違っていました。かなりかも。

スマホ(受信側)のBLEスキャン間隔はというと、以下にようになっています。

  • 低遅延モードLOW_LATENCY:常時スキャン
  • 低消費電力モードLOW_ENERGY:400msスキャン後4600ms休止、その繰り返し
  • バランスモードBALANCE:2000msスキャン後3000ms休止、その繰り返し

一方、BLEビーコンデバイス(発信側)の送信間隔はどうでしょう。
標準ビーコンで100ms、「Bluetoothリモートシャッター」は34msのようです(実測した結果)。

それではPochiruEcoはというと、こちらは特殊で標準ビーコンの規格を満たしていないようです。元々常時発信するデバイスではないのでそれでいいんでしょうね。ボタンが押されると800ms間隔で送信しつづけ、全体で20秒弱で停止します。

「実機ではスキャンできなかったり」の動作

上に紹介したスキャンモードのうち、低消費電力モードの場合5秒間のうち400msしかスキャンしないので、タイミングによっては、800ms間隔の送信を取りこぼす可能性があるようです。これで「実機ではスキャンできなかったり」の動作が説明できます。

「一回のボタン操作にもかかわらず2回以上信号を受けてスマホアプリを起動してしまうこと」

これについては、もう少し複雑な事情がありそうです。BLEのAPIライブラリの違いなのか、BLEビーコンデバイスとの相性の違いなのか不明ですが、BLEスキャンでデバイス検出できたあとの動作に微妙な違いが現れました。

コードで示すと


    // Device gatt callback.
    private BluetoothGattCallback leGattCallback = new BluetoothGattCallback() {
//        @Override
//        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
//            Log.d(TAG, "Bluetooth GATT Status: " + status);
//       }
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.d(TAG, "Bluetooth GATT Status: " + status);
            switch(newState){
                case BluetoothGatt.STATE_CONNECTED:
                    Log.d(TAG, "Bluetooth GATT State: CONNECTED");
                    gatt.disconnect();
                    break;
                case BluetoothGatt.STATE_DISCONNECTED:
                    Log.d(TAG, "Bluetooth GATT State: DISCONNECTED");
                    gatt.close();
                    break;
                default:
                    Log.d(TAG, "Bluetooth GATT State: " + newState);
                    break;
            }
        }
    };

の部分の話になります。

スキャン検出後、Gattに接続要求して、接続したら切断して、切断したらクローズして、というようなことをやって、BLEビーコンの発信を中断させるようにしています。上記コードには「接続したら切断して、切断したらクローズして」の部分が見えると思います。

ところが、実機によっては(もしかするとSDKバージョンによっては、かもですが)これがうまく動作しないものがあります。「Gattに接続要求して、接続したら切断して」の部分で接続時のコールバックがなく、いきなり切断時のコールバックになってしまいます。結局切断してクローズするのですから「どっちでもいいじゃない!」となりそうですが、このとき結構なタイムラグがあり、それがスキャン時の複数回検出に繋がっているのかと考えています。

BLEビーコンが発信を中断してくれさえすれば、5秒間隔位でボタンを押してもその都度スマホアプリが起動できますが、中断しないと、「一回のボタン操作にもかかわらず2回以上信号を受けてスマホアプリを起動してしまうこと」になってしまいます。

Android9.xの実機ではうまく動作しますが、Android7.xの実機では上記の通りの現象が出ています。

ただ、このあたりは、BLEビーコンの動作仕様といかに合わせるかの問題になるので、あまり厳密に考えても意味なさそうです。

たとえば、ボタン操作から20秒弱で発信停止するのあれば、最初からGatt接続しないで、20秒まってからスキャン再開すればよさそうです。もちろんその間ボタン操作は効かなくなるので、そうしたやりかたで要件を満足させられるのかチェックする必要はありますが。

Android9.xの実機(GalaxyJ6+)ではうまく動作しており、ボタン操作の取りこぼしなく、操作後1秒以内にカメラアプリが起動して撮影できることを確認しています。

関連する記事・ページ

GitHubに公開したAndroidアプリ「BleSwitch」について(技術解説)
GitHubに公開したAndroidアプリ「BleSwitch」について(使い方)
GitHubに公開したAndroidアプリ「BleSwitch」について(概要)

お世話になったリンク

Android 5.0におけるBLE について – 受信編 –
THETA プラグインで 市販の BLE ボタンをリモコンにしてみた
iBeaconとは

以上です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です