2016年6月15日

[android]BLE接続までに時間がかかることがあるが、解決せず

しばしば、connectGatt()を呼んでからonConnectionStateChange()までにやたらと時間がかかることがあるのだ。
10秒とはいかないが、そのくらい待つことがある。
かと思えば、さっさとつながることもある。

nRF Master Controlアプリではそういうばらつきがほとんどないので、私のアプリがよくないのだと思う。


logcatを見比べていくと、私の方ではこのログが出ていたのだが、nRF Master Controlアプリには出ていなかった。

D/BluetoothLeScanner: could not find callback wrapper

connectGatt()より後に出ているのだが、別にこれが何度も呼ばれているわけでもないし、待っている間も何かログが出ているわけではない。
なので、疑わしいのはこれか、という程度。

 

ソースファイルはこの辺だろう。
wrapperがnullだから、というくらいしかわからない。
Log.d()程度だし、あんまり関係ないような気がする。

 

気になるので出ている原因を調べたところ、私が悪かった。
BluetoothLeScannerでスキャンし、ボタンを押して接続させている。
接続するときにはスキャンを停止させる。
それだけならよかったのだが、ダイアログが消える処理のところにもスキャン停止を行っていた。
このログは、2回目にstopScan()を呼んで、もうコールバック関数の登録が消されたあとだから出力された、ということのようだった。

 

2重呼びを解消して安定した!ように見えたのだが、まだまだじゃった。。。


それ以外で違うログは、これの出力されるタイミングが早いか遅いかくらいしかない。

--------- beginning of system

私のアプリはconnectGatt()を呼んだ後で、nRF Master Controlアプリはずいぶん前だ。

でも、これって時間やプロセス名が出てないログで、これの前に空いているスペースの数も違うので、何か深いところで出している感じがする。


じゃあ、もしかしたら接続時ではなくて切断で足りていないものがあるのかもしれない。

D/BluetoothGatt: refresh()

私の方には、このログが出ていない。
が、BluetoothGatt#refresh()なんてAPIは引っかからないぞ?
・・・あ、これ@hideだ。
えー、リフレクションして呼んでるの??

 

refresh()で検索すると、キャッシュを使わずにサービス検索してほしい場合に呼び出しているようだった。
How to programmatically force bluetooth low energy service discovery on Android without using cache - Stack Overflow
それだと、別にキャッシュは使ってもらって構わないなぁ。
むしろ、キャッシュ使ってもいいから早く接続完了させておくれ、というくらいだ。
まあ、サービス走査は接続した後だけどね。。。

書いてあったメソッドをそのままコピーして呼び出してみたが、うん、早くはならなかったよ。


わからんかった。
悔しいが、保留だ。
だれか教えてくだされ~~~

2016年6月14日

[java]CountDownLatchは再利用しない

BLEの非同期処理を、CountDownLatchで同期にしようとしている。
が、1回目はうまく行くのだが、2回目は結果がうまく返らない。
ログを出してみた問頃、同期待ちにならず、するっと抜けている。

 

CountDownLatch (Java Platform SE 6)
カウントはリセットすることができない、とのことだ。
リセットしたい場合はCyclicBarrierを検討しなさいとのこと。

EffectiveJava第2版の項目69を読むと、CyclicBarrierは使用頻度が低いらしい。
理由はわからんが、じゃあCountDownLatchを使うたびにnewすればいいだろう。


ここまでのソースだ。
hirokuma/AndroidTwoSpinners at a869bfa3af06cbdc19a618ca1877fd8efc568632
何かもう、最初のTwoSpinnersの面影がなくなってきつつあるな。。。

CountDownLatchで待ったりカウントダウンしたりさせているのは、この辺。
writeだと、ここで待たせて、ここでカウントダウンしている。
readやDescriptorの設定も似たようなものだ。

 

さて、非同期で返ってきた値を同期で参照しようとすると、間にグローバル変数というか、共通で読むことができるメモリがいる。
今のところ、それはBundleを使っている。
何でかというと、元がそういう感じだったからだ。

何だかよくわからないが、便利そうだ。
ただ、よくわからんのでちょっと怖い。。。

JavaなのかAndroidなのか、とにかく、同じようなことをやるのにいろいろ手段があるように感じてしまうのだ。
そして、それはたぶん同じではないので、使い分けがいるのだろうと思う。

が、1パターンを知ってそれで動いてしまうと、そこで立ち止まってしまうのよねぇ。
かといって、全部知ってから実装するなんてのは、まあ無理だ。
そこら辺をどうやって調べるなり、安全性を確保するなりするのかが、わからずに困っているところだな。

2016年6月13日

[android]Handlerの変数でLintの警告が出る

Hnadlerの変数で、Lintの警告が出ている。

 

これだと何も言われない。
private Handler mHandler = new Handler();

なのに、こうすると、なにやら警告が出てくる。
TwoSpinnersで、BLE用に作ったサービスからのコールバックを受け取るここですな。
private Handler mHandler = new Handler() {};

 

このHandlerクラスをstaticにしないとメモリリークするかもしれんぞ、というような内容だ。
じゃあ、static変数にすればいいや、とstaticを頭に付けたのだが、変わらない。

そういう話ではないということ?
ここに至って、ようやくJavaについて調べることにした。

 

classの中に書くclassには、いくつか種類がある。
この呼び名だが、なんかいろいろある。。。
今のところオラクルのドキュメントが正になる気がするので、そこから見ていこう。


まず、大きなくくりとしてNested Classesと呼ぶようだ。
staticがついたものをStatic Nested Classes、staticがついていないものをInner Classesとしてある。
ちなみに、Nested Classesの外側になるのは、Outer Classesだと思うが、文章ではenclosing classとも書いているから、そっちかもしれん。

「Nested classesは2つのカテゴリに分けられる」とあるから、この2つがそのカテゴリになる。
こう書きつつも「Non-static nested classes(inner classes)」と括弧で書いているから、何だかわかりづらい。
用語を作ったのなら、もう力で押し切ってほしいのだが。。。

 

Static Nested Classesは1種類だけだが、Inner Classesの方は別パターンが2種類ある。
1つがLocal Classes、もう1つがAnonymous Classes。

そして、Static Nested Classes、Inner Classesと同列に「Shadowing」「Serialization」という項目がある。

「Shadowing」は、引数と、Nested Classesのフィールドと、Enclosing Classのフィールドに同じ名前のものがあった場合のサンプルソースが載っている。
そういう場合、Nested Classの中からはEnclosing Classのフィールドは触れませんよ、というのが、隠されている(shadow)という意味なのかな。

「Serialization」は、Inner Classesをシリアライゼーションするときは注意せんといかんですよ、ということを言っているようだ。
今回のHandlerの話を検索すると、コンパイラが自動的にメソッドを作るなどという言葉が出てきていたので、これが関係しているのかもしれん。
the moon at dawn: handleleakがうざったい。

 

というわけで、こうだ。

  • Nested Classes
    • Static Nested Classes
    • Inner Classes
    • Local Classes(Inner Classesの別バージョン)
    • Anonymous Classes(Inner Classesの別バージョン)

別バージョンというか、special kinds of inner classesとあるから、派生したパターンとかかもしれん。


うーん。

staticが付いている方は、そこそこ独立性が強いから"Nested"として、staticが付いていない方はEnclosing Classに取り込まれているところが強いから"Inner"としたのかしら。

そして、これに日本語の説明が加わると、どの用語がどれなのかわからんごとなってくる。

ここら辺が、どういう名前で呼ばれているのかの参考になりそう。
匿名クラスとかローカルクラスとか - 日々常々

 

中身を省略したLocal ClassesとAnonymous Classsesだが、上記リンクに説明があるのでそちらを読んだ方がよいだろう。
でも、せっかくなのでオラクルの方を眺めておく。

  • Local Classes
    • ブロックに書いたclass
    • メソッドの中に書くのが普通かね
    • (個人の感想)みんな「使わない」って書いてるから、使わないんだろう
  • Anonymous Classses
    • classの宣言と具体化を同時にできる
    • Local Classesと似ているけど、彼らには名前がない
    • (個人の感想)Anonymous ClasssesのためにLocal Classesという仕様が必要だった、ということか

というところまで見ていって、ようやく最初に戻る。

なんでHandlerの変数にstaticを付けてもダメかというと、あれはAnonymous Classsesだから、カテゴリとしてInner Classesになるからだ。
Lintが言いたいのは「Static Nested Classesにしようよ」だから、やり方を変えないといけないのだな。

 

まあ、しょせんLintの警告だから、問題がなければスルーしてよいのだ。
だけど、安全に書く方法があって、特にそれで問題がないなら、変更しようかね。

[android][ble]位置情報サービスも有効にしないとスキャン結果が戻らない

先週書いたAndroidのBLEアプリサンプルを動かした。
が、なぜかBLE Peripheralのスキャンをしても画面に表示されない。
エラーなどは出ていないのだが、onScanResult()がコールバックされないので、画面に出てこないのだ。

じゃあスキャン自体動いていないのかと思ったが、Logcatの方にはデバイス名が表示されるし、設定アプリのBluetoothを開くとデバイス名が出てくる。
アプリ情報を見ても、位置情報は許可している。
Blueoothを入り切りしたり、電源を入れ直したりしたが変わらない。
もう1台あるAndroid端末に同じアプリを入れると、こっちはスキャンされる。

なんじゃこりゃ?と思ったが、Android端末自体の「位置情報サービス」が有効になっていなかった。
有効にしたら、動いた。

image


BLEが無効だったら確認するし、アプリの位置情報許可がなければ確認するのだけど、位置情報サービスは考えていなかった。

こちらが詳しい。
Android 6.0でBLEデバイスのスキャン結果を受け取るには位置情報モードをオンにする必要がある - Qiita

うん、こういう動きだった。
設定アプリでスキャンできたのは、たぶんPEERS_MAC_ADDRESSパーミッションがついているからじゃなかろうか。

 

v6.0.0_r1のソースだと、ここら辺。
これをまねして、TwoSpinnersに追加したのがこちら。
getInt()しているから、たぶんSQLiteから直接設定値を持ってきているのだろう。

Intentで設定画面に飛ぶようにしたのだが、アプリを起動していきなりジャンプすると何が起きたかわからないので、Toastを表示させるようにしている。

また、onResume()したときにもう一度チェックするようにした。
無効な場合は、ボタンを押せなくしておけばよいだろう、という作りだ。

 

今回は、hasScanResultPermission()から真ん中だけ抜き取ったけど、全部まねするか、hasPeersMacAddressPermissionだけ外すとか、そういう方がよいかも。
うちのNexus5はAndroid6.0.1だけど、全部のバージョンで位置情報サービスが必要というわけでもないようだからだ。

技適の検索 (2)

日本で使えるnRF52832の安いモジュールはまだ出ないのだろうか。。。

海外で新しいBLEモジュールが発売されても、日本の技術基準適合証明を通るまでは買いづらい。
nRF52のDKなんか安いのだけど、そういう理由で買っていない。
電波暗室を設置してまでやるつもりはないので、ソフトだけやる私のような人は出遅れてしまう。

 

さっきGoogle検索すると、まだ太陽誘電さんしかなさそうだ。
名前のルールはわからんが、おそらく4文字目が「G」なのがnRF51822やnRF51422で、「H」がnRF52832なのだろう。

DigiKeyやMouserでは売られているのだが、技適はどうなってるのだろうか。

総務省で検索したが、たぶんこれだろう。

image

名前はこうなっている。

  • モジュール単体:EYSHCNZXZ
  • 評価ボード:EBSHCNZXZ
  • 評価キット:EKSHCNZXZ

こういう名前単位で取得するのか、モジュールだけ取得してボードやキットはそれを使うから取得しなくてよいのかがよくわかってない。
「設計認証」だから、同じ設計であればよい、とかだろうか。。。

ともかく、EBSHやEKSHでは出てこず、EYSHだけが出てきた。
でも「EYSHCNZXZ」だと出てこないので、なかなか検索キーワードが難しい。

 

じゃあこれを買うか?というと、うーん、ちょっとお高いですな。
まあ、一般向けじゃないし、数多く売れるわけでもないから仕方ないのでしょう。

2016年6月11日

[android][ble]BLE接続する (3) - 最終回

3回目。
今回はCharacteristicのアクセスを見ていく。

AndroidでのBLEアクセスについて調べる、というよりも、Bluetooth Developer Studioで生成されたAndroid Clientのソースをなるべく流用して楽にBLEアクセスするアプリを作るのを目的としているので、そこら辺はご容赦を。

なるべく、既存のアプリを機械的に変更するだけでBLE対応できるようにしたいと思っている。
まあ、まだちゃんとしたAndroid/BLEアプリを作ったことがないので、何でもかんでもはできないだろうが、勉強だからよいのだ。


はじめる前につらつらと考えていたのだが、BLE接続してしまえば、アプリによってはUIなどなくても勝手にRead/Writeできるはずだ。

接続も、ペアリングしていればUI無しでよいのかもしれない。
ペアリング無しの機器であれば、最初からUI無しでも接続できるだろうが、さすがにそれはちょっと怖い。
基本的には人見知りで、知り合いになった後であれば気楽に話せる、というのがよいだろう。

 

ここは、もうちょっと慣れてからだな。


話を戻そう。

BDSサンプルでは、PeripheralControlActivityで値の読み書きをしている。
こんな画面だ。

image

ベースはこちらだが、ReadとWriteだけだと足りないので、Write without Response、Notification、Indicationを追加している。
nRF51822のソース
Nordic pluginsをそのまま使うと、UINT8_ARRAYの書込みでHardFaultが発生するのを忘れていてはまってしまった。。。

 

PeripheralControlActivityでは、こんなしくみになっている。

  • Write
    1. 該当するTextViewに16進数を書込んで、ボタンを押す
    2. PeripheralControlActivityのonWrite()が呼ばれる
      1. TextViewが持つandroid:tagを取得
        • tagにはサービスUUIDとキャラクタリスティックUUIDが載っている
          例:gatt_op_B7B851C6D7B847B38F93773756B46F9A_B7B80010D7B847B38F93773756B46F9A
      2. tagを分解して、サービスUUIDとキャラクタリスティックUUIDを取得
      3. 取得したUUID達から元になったUI部品を検索(EditTextになるみたい)
      4. 検索できたEditTextから文字列を取得
      5. 取得したUUID達からCharacteristicPropertiesを取得
        • CharacteristicPropertiesは自作classで、キャラクタリスティックが書き込めるかどうかなどの情報を持たせている・・・のだが、これは自動的取得するのではなくonCreate()のときに1つずつ設定している。
        • nRF Master Controlアプリは相手の情報を知らなくてもやっているから、自動でできるんじゃないの?
      6. 書き込み可能かチェック
      7. EditTextに書込まれている文字列が16進数として妥当かチェック
      8. BleAdapterService#writeCharacteristic()で書込む
    3. 書込が終わったら、handleMessage()が呼ばれる
      1. GATT_CHARACTERISTIC_WRITTENイベント

こんなもんだろう。
Characteristicの属性チェックを省けば、以下があればよいことになる。

  • BleAdapterService
  • サービスUUID
  • キャラクタリスティックUUID
  • 書込みたい値

このUUIDだが、ハイフンを付けた文字列のようだ。
"0000XXXX-0000-1000-8000-00805f9b34fb"みたいなやつ。
BleAdapterServiceにUUIDの定義はあるのだが、そちらはハイフン無しの16進数だ。
変換は、Utility.normaliseUUID()でできる。

できるけど、ハイフン無しの形式で持つ理由がないと思う。
使ってないし。
それならいっそのこと、最初からハイフン付きで生成した方がよさそうだ。

 

Readについても、流れは同じ。
結果はコールバックで戻ってくるので、テスト先で処理したい場合は、そこに流すしくみが必要になる。

Notification/Indicationもだいたい同じだが、こちらは先にCCCDに書込みをして有効にしておかねばならない。
今のところ、nRF51822でNotification/Indicationするしくみを作っていないので、今回はここまで。


今回までのAndroidソース
BDSのAndroid Clientプラグインソース

そう、とうとうプラグインの動作を変更するところに手を染めてしまった。
といっても、128bit UUIDをハイフン区切りにするだけなのだが。
テンプレートは、ログを出す部分をどうするか迷いつつ、BleAdapterServiceのgetService()をpublicにした。
Activityから使いたいとなると、別パッケージになっても使えた方が便利だからだ。

 

やることはまだあるのだけど、読み書きについては流れがわかったつもりなので、シリーズは今回で終わりにしよう。

[bds]Characteristic設定を128/16bit設定は伊達じゃない

image

この赤枠で囲んだところの話だ。
UUIDの表示を16bitにするか128bitにするかなのだが、Pluginによるソース生成にも影響を及ぼしていた。

 

Android Clientの場合、名前として「サービスUUID_キャラクタリスティックUUID」という文字列を作ることがしばしばあるのだが、そのキャラクタリスティックUUIDが16bitで出力される。
しかし、内部では128bit前提になっているため、いろいろ一致しないでnullになったりしていたのだ。

 

Nordic Serverの場合も似たようなもので、service_init()で16bitとして処理しようとするためか、サービスのUUIDは128bitで、キャラクタリスティックのUUIDは16bitにしようとしてしまい、変なことになる。
何というか、Generic Access ServiceのUUIDをベースにした128bit UUIDになっているようだ。

 

不具合やん!と思ったのだが、ちゃんと登録した企業であれば16bit UUIDが使えるからね。。。
128bit UUIDで使いたいなら128bitで、16bit UUIDで使いたいなら16bitで、ということだ。
見た目だけじゃないってことですな。

[android][ble]BLE接続する (2)

前回はBLE接続しただけで終わった。

しかし、あっさり「BLE接続」と書いているが、どこまでシーケンスが進んだら「成功」と見なしているのだろうか?
それに、このconnect()は同期で結果が返ってきているのだけど、だいたいこういうのは非同期でやるものではなかろうか?

疑問が尽きないので、connect()が何をしているのか見てみよう。


BleAdapterService.java#L212

やっているのは、これ。

  1. BLEアドレスからBluetoothDeviceを取得(メンバ変数…じゃなくてフィールド)
  2. BluetoothDevice#connectGatt()

引数にcallbackとか着いているから、これは接続要求を出しただけだろう。
それならば、納得だ。

 

コールバックになっているmGattCallbackが、大きい。
L71~L170まである。
中で持っているのは、これら。

  • onConnectionStateChange()
  • onServiceDiscovered()
  • onCharacteristicRead()
  • onCharacteristicWrite()
  • onCharacteristicChanged()
  • onDescriptorWrite()
  • onReadRemoteRssi()

なんとなく名前でわかるようにしてあるところが偉いな。

Changedは状態変化通知、特にonCharacteristicChanged()はNotification/Indicationだろう。
Read, Writeは要求した結果が返ってくるだろう。Write Without ResponseでもonCharacteristicWrite()は呼ばれたと思う。

 

というわけで、connectGatt()したらonConnectionStateChange()が呼ばれるはず。
L80でサービスを見に行くようにしてあるのだろう。
そしたら、onServicesDiscovered()が呼ばれるはずだ。

さて、ではこれがどうやってActivityと会話しているかというと、たぶんMessage.obtain()というやつだろう。
前回、よくわからないままコピーしたものがいくつかあるのだが、ActivityにHandlerを追加しているのだ。

Handlerは、スレッド間通信のしくみらしい。
Handlerをnewした方がサーバになって、メッセージをobtain()したときだけhandleMessage()が実行される、ということだろうか。

ちょっと話が脱線するが、Androidアプリは同一プロセスで動いているんじゃなかったっけ?
スレッド間通信といっても、同じプロセス内だったら関数コールでもなんでもいいんじゃなかろうか。。。
mutexとか、そういうのをJavaがうまいこと隠蔽しているのかも。

ともかく、ログを入れて試したところでは認識通りのようだ。
connect()を呼ぶと、handleMessage()のGATT_SERVICES_DISCOVEREDまで呼ばれて終わった。

 

元のBDSサンプルでは、数字を打ち込むTextViewとWriteやReadのButtonが並んでいる画面が表示される。
接続するまでは非アクティブで、接続するとアクティブになる。
そういった処理をこのhandleMessage()でやるのだな。

わかった気がする。

 

では、次回はCharacteristicのアクセスについて見ていこう。
BDSサンプルだと、UUIDをxml側に書いているから、そこをどうするか考えないとねぇ。


コールバックされる内容と、Activityへの通知方法がわかったので、なんとなくだが理解の半分くらいまで届いたんじゃなかろうか、という気がしている。

この「気がしている」という感覚が大切で、わからんわからんと思っているだけだと、けっこうつらいのよね。。。
長いことこういうお仕事してるけど、いつかは「わかった!」という瞬間が来るはず、という自信が支えているところはあるねぇ(偽りの自信かもしれんが)。

2016年6月10日

[android][ble]BLE接続する (1)

ようやくここまで来たか。。。

 

ベースとしているBluetooth Developer StudioのAndroid Clientプラグインでは、一覧を表示するActivityとBLE操作をするActivityが別になっている。
その際、BLE操作するActivityに渡しているのは、以下。

  • デバイス名
  • デバイスアドレス

これだけなのだ。
BluetoothDeviceの中身をまるまる渡すようなことをしているのかと思ったが、そうではないのだな。

そして、接続時にやっているのは、これ。

BleAdapterService mBluetoothLeService;
mBluetoothLeService = ((BleAdapterService.LocalBinder)service).getService();
mBluetoothLeService.connect(mDeviceAddress);

まとめて書いたけど、実際はServiceConnectionというサービスをnewしてoverrideしたonServiceConnected()の中でmBluetoothLeServiceを取得して、接続ボタンを押したonConnect()の中でBleAdapterServiceのconnect()を呼んでいる。

このconnect()はプラグインが提供しているBleAdapterServiceクラスが持っている。
他にもBleAdapterServiceは便利そうな関数を持っているから、これを使うとよいのだろう。


考えることはいろいろあるが、まずは接続だけしてみる。

 

よくわからないが、connect()にはBleAdapterServiceがいるので、関係するものをBDSサンプルから持ってきた。

ActivityのonCreate()あたりでbindService()するようだ。
AndroidのServiceは、バックグラウンドで動いてくれるしくみらしい。
はじめ方としてstartService()とbindService()の2種類あるらしいが、元のまねをしてbindService()にする。

bindService()するのに、ServiceConnectionのインスタンスがいる。
これもよくわからんが、ServiceConnectionのインスタンスを作るときにoverrideするonServiceConnected()でBleAdapterServiceを取ってきている。

 

これだけ書いて動かしたのだが、onServiceConnected()が呼ばれない。。。
さんざん悩んだが、単にAndroidManifest.xmlに<service>を書いてやらんといかん、というだけだった。
エディタで「<service」くらいまで書くと、候補で勝手にクラス名まで選んでくれた。
そこまでできるんだったら、サービスの定義が入ってないのを指摘してくれたらよかったのに(ログは見てないけど)。


ともかく、これでmBluetoothLeServiceに中身が入った。
あとは、mBluetoothLeService.connect()にデバイスアドレスを付けて呼ぶだけだ。
前回作ったコールバック関数というかListenerではBluetoothDeviceを渡しているので、問題なく呼べる。

うん、接続できた。
スニファで見ても、Advertisingが止まった。

ここまでのソースは、こちら。

 

うーん、BLE接続できたのに、感動が薄い。
単にBLE機器を接続しただけだからと言われればそれまでだが、一覧を出して選択するまでで感情を使い切ってしまったのだろう。

加工したい人向けにはこういうやり方でよいとして、BLE Peripheralの選択くらいまではOSが吸収してくれんかのぅ。
せっかく設定アプリがあるのだから、接続した後だけやりたいのだが。


と、ごちゃごちゃ書いたが、BLE接続だけしておしまい、というわけにはいかんだろう。
Characteristicへのアクセスもあるし、Notification/Indicationの取得もある。
それに、よくわかってないServiceもある。

 

Android開発に終わりはないのだ!というわけで、次はCharacteristicなどを見ていきましょうかね。

2016年6月9日

[android]DialogFragmentから元のActivityに結果を返したい

くっ、BLE接続の前にもう1段階あった。。。

まあ、ダイアログ側でBLE接続をしてもよいのだけど、とにかくダイアログで行った結果を呼び出し元のActivityに返したい。

 

検索すると、いろいろ出てきはするのだけど、だいたい「やりたいことに対して実装が多いので簡略化する方法を考えた」というパターンが多い。

onActivityResult()なんかで返せるのかと思っていたのだが、そういう時代ではないみたいだ。


現状のソースはこちら。

 

Activity側では、ダイアログをこの順番で表示させている。

  1. DialogFragmentをextendsしたクラスをnewする
  2. そいつをshow(getFragmentManager(), "xxx")する

DialogFragmentの説明を見ると、呼び出し元のActivityでイベントハンドラを作っておいて、DialogFragmentの方はgetActivity()したものをキャストしてイベントハンドラを呼び出している。

キャストするとちょっとガチガチすぎるので、interfaceとか作っておけばよいのかな。
あれ、でもgetActivity()で取ってこれるのは単なるActivityだ。
それがinterfaceをimplementsしているとかわかってくれないんじゃないか?

・・・エラーにならない。
こんなのでいいんだ。
なんか、Javaってこういうダウンキャストに対しては厳しいというイメージだったのだけど、不意に見せる優しさなのかね。
こういうギャップにぐっと来るのかもしれない。


BluetoothAdapterを渡すためにメソッドを追加したのだけど、どうもsetArguments()で渡す方がよいらしい。
Y.A.M の 雑記帳: Android Fragment で setArguments() してるサンプルが多いのはなぜ?

ほほう。
サンプルを見ると、DialogFragmentをextendsした方にnewInstance()を作って、その引数に入れてもらっているようだ。
そしてsetArguments()するところは呼ぶ人からは隠している。
よし、まねしよう。

と思ったのだが、私が渡したいのはBluetoothAdapterだ。
オブジェクトのようなものは、Serializableなどになっていないといけないみたいだ。
使いたいのはBluetoothLeScannerだから、それが得られるようなものであればなんでもよいのだけど。。。

 

しかし、getActivity()の存在を知ったので、そこからgetSystemService()してgetAdapter()すればよいことがわかるのだった。
つまり、今の時点では引数はいらないということだ。

 

今日までのソースは、こちら。
次回こそ、次回こそはBLE接続のはず。。。

https://github.com/hirokuma/AndroidTwoSpinners/tree/618c641d9b6c6b925dc9853b2b416749aa6b3726/app/src/main/java/com/blogpost/hiro99ma