[解決済み] デバイスを強制的に検出モードにすることなく、近くにあるすべてのBluetoothデバイス(ヘッドセット、電話など)を見つけることができます
質問
私の目標は?
私のAndroidアプリケーションから、近くにあるすべてのBluetoothデバイス(電話、ヘッドセットなど)を検出すること。
以下はその例です。 デベロッパー.android.com は、ペアリング済みのデバイスのリストとともに、近くにあるBluetoothデバイスを検出します。
私の状況
2台のBluetoothヘッドセットの電源が入っていて、Bluetoothスキャンに成功した後に検出されませんでした そこで、この問題を調べてみたところ、Bluetoothヘッドセットをペアリングモードに切り替えると、アンドロイドに検出されることがわかりました。
ヘッドセットをペアリングモードに切り替えるには、電源を入れた状態で電源ボタンを長押しする必要がありました。そして、そう、ついに、私のアプリケーションからのスキャンでBluetoothヘッドセットが検出されるようになったのです。
私の問題点
ペアリングモードに切り替えなくても、ヘッドセットが自動的に検出されるようにしたい。電源が入っている近くのBluetoothデバイスをすべて検出する方法が見つかりませんでした。
解決方法を教えてください。
Android の bluetooth 検出に関して、ブログ、スレッド、ドキュメント、SO の回答などを読んで、私が見つけたすべてをここに記します。これは、私の発見をここに投稿するのに役立つかもしれないと思った。
そこで、誰かが読み始める前に、明らかにしておきたいことがあります。 電源は入っているが、検出できないBluetoothデバイスが近くにあることを検出する方法は見つかりませんでした。
近くにあるすべてのBluetoothデバイスを検出する
私の主なターゲットは、近くにあるすべてのブルートゥースデバイスを検出することです。そのために
BluetoothAdapter
クラスがあり、そのクラスは
startDiscovery
関数を使って、近くにあるBluetoothデバイスをスキャンすることができます。なぜなら、AndroidによるBluetoothスキャンで検出されるためには、Bluetoothデバイスが検出可能である必要があるからです。私が欲しいのは、強制的に検出可能にすることなく、近くにあるすべてのBluetoothデバイスを検出することです。この目的を達成するために、私はソリューションを探し始めました。
まず勉強したのは Bluetoothプロトコル と、ブルートゥースの検出、接続、ペアリングに使用される基本的なプロトコルを発見しました。Android では、電源は入っているが検出可能な状態になっていない BT デバイスを検出するための API が見つかりませんでした。
クラス0x00のBluetoothデバイスは無視される
この検出の問題を、Bluetooth デバイスを強制的に検出可能なモードにすることなく掘り下げると、自らを「Second」と宣伝している Bluetooth デバイスを発見するポイントにたどり着きました。
class 0×00
は、近くのBTデバイスのスキャンを実行している間、自動的に無視されます。この問題については、いくつかの場所で述べられています。ここでは、そのいくつかを紹介します。
この問題の回避策を探したところ、はい、見つけました。ただし、この回避策に付随する文書やレビューには、すべての種類のAndroidデバイスで動作するわけではない、と書かれています。とにかく、代替スキャンはデフォルトのBTスキャンと同じですが、いくつかの追加作業を行います。BT スキャンが成功した後、Android ログを読み、BT デバイスがスキップされていないかどうかを確認します。これは、以下のような簡単なハックです。 こちら . 同じ回避策について議論しているgoogleグループがあります。 こちら .
上記の回避策も私の問題を解決してくれません。Bluetoothヘッドセットは、BTスキャンで検出されるために、検出可能である必要があります。Android が近くの BT デバイスをスキャンしている間、ヘッドセットがスキップされることはありません。単に検出されないだけです。
Bluetoothページスキャン
しかし、再び解決策を探し始めたところ、また面白いものを発見しました これは、別の スタックオーバーフローの回答 というのがあります。 ブルートゥースデバイスが検出不可能なモードであっても、最初に完全なMACアドレスを知ることによって、そのデバイスが近くにあるかどうかを知ることが可能です。 . 今後の参考のため、彼の回答から再度引用します。
<ブロッククオートテクニックとしては、PAGEリクエストを試して、シークしたBluetoothホストMAC識別子を構成する6バイトすべてを送信することです。PAGEリクエストは、BluetoothスレーブのBT ADDRを知ることで、そのスレーブとの接続を可能にします。発見不能モードのデバイスは、問い合わせスキャン(デバイス発見意図)には応答しませんが、以前から知られている別のデバイスに接続したいデバイスが使用するページスキャンには応答します。
希望が見えたので、Androidでページスキャンを開始するにはどうしたらいいか、検索し始めたのですが、今回も失敗しました。ページスキャンを開始するためのAPIのようなものは見つかりませんでした。Androidのドキュメントにある
BluetoothAdapter
クラスで、BTスキャンが開始されるとき、私はそれを知るようになりました。
通常、約12秒間の問い合わせスキャンが行われ、その後、新しいデバイスごとにBluetooth名を取得するためのページスキャンが行われます。
Androidのドキュメントにはページスキャンについての記載がありますが、意外にもページスキャンに関する他のドキュメントはどこにもありません。そこで スタックオーバーフローの質問 をご覧ください。
BTIDのリストを"already paired"のリストに追加することによって、androidを"fool"することができますか?
いいえ、そのような方法は見つかりませんでした。Androidのbluetoothペアリングの仕組みについて読みました。以下はその例です。 フロー図と詳しい説明書 . Androidの隠しAPIを使おうとしていたところ、Reflectionを使っていくつかの隠しAPIを使うことができました。そして、私の目的を果たすために使えそうな隠しAPIを探し始めたのです。しかし、残念ながら、Android のペアリング済みリストに BT デバイスをプログラム的に追加するための hidden API を見つけることができませんでした。
bluetoothのペアリング、隠しAPI、リフレクションによる呼び出し方法について確認するのに役立つリンクをいくつか紹介しますので、今後の参考にしてください。
そこで、BTデバイスが検出可能モードで、Androidのペアリング済みリストにない場合、ペアリングすることができました。私の場合、ブルートゥースヘッドセットを使用しました。電源を入れ、発見可能な状態にしました。ヘッドセットのBTアドレス(MACアドレス)は分かっていました。そこで、私は関数を呼び出した
createBond
を私のコードからリフレクションを使って実行すると、完璧に動作しました。デバイスはAndroidの"already-paired"リストに正常に追加されました。私の目的を果たすためのソリューションを求めて歩き回っているうちに、面白いものを見つけました...。
ペアリング済みデバイスに関する興味深い観察
アンドロイドは、すでにペアリングされたデバイスを削除しても、そのデバイスをメモリ内に保持することがわかりました。この発見をより良く理解するために、事例を紹介しましょう。私の場合、ヘッドセットは以前にペアリングされていました。
- Androidからヘッドセットのペアリングを解除する/忘れる
- その後、ヘッドセットの電源をオフにした。
- その後、近くにあるBluetoothデバイスのスキャンを開始
- もちろん、ヘッドセットは見つかりませんでした
- しかし、Androidのログを調べたところ、Androidはそのヘッドセットのボンディング状態(パーリング状態)の変化を記憶していることがわかりました。
- 以前ボンディングされたヘッドホンをスキャンして、リモートデバイスがダウンしていることを報告しました。
以下は、以前ペアリングし、その後ペアリングを解除したヘッドセットのMACアドレスとともに出力されたログです。
PREV_BOND_STATE = 11 // BOND_BONDING (BluetoothDevice.java)
BOND_STATE = 10 // BOND_NONE
REASON = 4 // UNBOND_REASON_REMOTE_DEVICE_DOWN
そしてまた、同じテストを実行しましたが、今度はブルートゥースヘッドセットをオンにしてみました(検出不可)。この場合もヘッドセットは発見されませんでしたが、興味深いことに、今回は別のログが出力されました。
PREV_BOND_STATE = 11 // BOND_BONDING (BluetoothDevice.java)
BOND_STATE = 10 // BOND_NONE
REASON = 2 // UNBOND_REASON_AUTH_CANCELLED
は
REASON
が変更されているため、Android が bluetooth ヘッドセットと接続しようとしたことが理解できます。ヘッドセットは検出可能なモードではありませんでしたが、Android はヘッドセットを検出し、以前ペアリング済みリストにあったヘッドセットと接続しようとしました。
を追加してブルートゥーススキャンを実行中にこのログが出力されました。
ACTION_BOND_STATE_CHANGED
アクションに
intent.addAction
.
Androidをビーコンとして使用することはできますか?
しかし、その場合、AndroidもBLEであることを宣伝する必要があります。これはAndroidの新機能であり、これまですべてのデバイスがこの機能をサポートしていたわけではありません。以下はその例です。 デバイス一覧 Bluetooth LEアドバタイズメント機能をサポートする しかし、Bluetooth LEアドバタイズは非常に低消費電力で高性能なので、Androidの次の大きなトレンドになると思います。
今後の研究に役立つリンク集です。
- AndroidはiBeaconとして機能しますか?
- iBeaconとしてのAndroid 4.4
- Android Beacon ライブラリ
- GithubにあるAltBeaconライブラリ
- AltBeaconについてもっと知りたい
- 広告を出すために携帯電話をRoot化する
ブルートゥース操作に便利な関数とライブラリ
関連
-
[解決済み】Android TextView : "setTextで表示されたテキストを連結しない" について
-
[解決済み】react-native: コマンドが見つかりません。
-
[解決済み】シンボル 'AppCompatActivity' を解決できない。
-
[解決済み】Android Studioの初回起動。Android SDKアドオンリストにアクセスできない
-
[解決済み】onCreateOptionsMenu(Menu メニュー)とは何ですか?)
-
[解決済み】Android Studioです。「プロジェクトが C ドライブに作成されている場合、「タスク ':app:mergeDebugResources' の実行に失敗しました。
-
[解決済み】レンダリングの問題 レンダリング中に発生した例外:com/android/util/PropertiesMap [重複].
-
[解決済み] TypeError: cb.apply は関数ではありません。
-
[解決済み] Android Studioで「URIが登録されていません」と報告されるのはなぜですか?[クローズド]
-
[解決済み] コンパイルした.apkを端末にインストールしようとするとINSTALL_FAILED_UPDATE_INCOMPATIBLEが表示される
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Android - SDKバージョン23のアップデート後、ACTION-VIEWインテントフィルタを持つアクティビティを少なくとも1つ追加する。
-
[解決済み】Android Studioでパラメータ化されたユニットテストを実行すると、指定されたインクルードに対するテストが見つからないエラーが発生する
-
[解決済み】Android Studio。adbバージョン」の結果を取得できない
-
[解決済み】ビットマップを保存する場所について
-
[解決済み】SDKの場所がandroid studioで見つからない。
-
[解決済み】'dependencies' を '(groovy.lang.Closure)' に適用できない。)
-
[解決済み】Couldn't load memtrack module Logcat Error
-
[解決済み] コンパイルした.apkを端末にインストールしようとするとINSTALL_FAILED_UPDATE_INCOMPATIBLEが表示される
-
[解決済み] ADBエラー:デーモンに接続できない
-
[解決済み] APKのインストール中にDELETE_FAILED_INTERNAL_ERRORエラーが発生する。