5.9 プロファイルのサポート プは、 BluetoothHealthAppConfiguration オプジェクトの getRole メソッドで 取得できます。 SINK タイプは複数の SOURCE タイプの機器から情報を受け取 ることができますがその反対はできません。 Andr 。 id アプリケーションを作成する場合、接続したヘルス機器から情報を取 得して画面に表示させることが一般的ですので、上述した registerSinkAppCon- figuration メソッドの引数のデータタイプは BIuetoothHealth. SINK_ROLE に します。 BIuetoothHeaIthCaIIback が持つコールバックメソッドは、 onHealthApp- ConfigurationStatusChange 、 onHeaIthChanneIStateChange があります。 onHealthAppConfigurationStatusChange メソッドは、ヘルス機器の登録状 態が変わったときにコールバックされるメソッドで、第 2 引数に次の値が入って きます ( 表 5.4 ) 。 表 5.4 onHeaIthAppConfigurationStatusChange メソッド 値 APP APP APP APP CONFIG CONFIG CONFIG CONFIG REGISTRATION SUCCESS REGISTRATION FAILURE UNREGISTRATION SUCCESS UNREGISTRATION FAILURE 説明 登録成功 登録失敗 登録解除成功 登録解除失敗 onHeaIthChanneIStateChange メソッドはチャンネルの状態が変更されたと きにコールバックされるメソッドで第 3 引数 ( 変更前の状態 ) と第 4 引数 ( 変更 後の状態 ) に次の値が渡されます ( 表 5.5 ) 。 表 5.5 onHeaIthChannelStateChange メソッド STATE STATE STATE STATE CHANNEL CHANNEL CHANNEL CHANNEL CONNECTING CONNECTED DISCONNECTING DISCONNECTED 説明 接続処理中 接続完了 切断処理中 切断完了 コールバックを登録したら、 BIuetooth ヘルス機器への接続を行います。接 続には BluetoothHeaIth クラスの connectChanneIToSource メソッドを使用し 121
第 3 章センシングデバイス リスト 3.17 : 接続失敗時のイベントコールバック @0verride public void onConnectionFai1ed(ConnectionResuIt argO) { / / Goog1e P1ay services の接続に失敗 ConnectionCaIIbacks は接続時と切断時に呼ばれます ( リスト 3.18 ) 。 リスト 3.18 : 接続時・切断時のイベントコールバック @Override public void onConnected (Bundle argO) { / / Goog1e P1ay services に接続した @Override public void onDisconnected() { / / Goog1e P1ay Services と切断した 実装では Google Play Services への接続と切断を明示的にを行う必要があり ます。この辺は通常のセンサーと同じように実装できます。 ・ onCreate または onResume : LocationCIient を取得する ・ onResume : LocationClient#connect で接続する ・ onpause : LocationClient#disconnect で切断する 位置情報の取得 : LocationCIient#getLastLocation を利用する また、気をつける点として LocationCIient#connect は非同期関数で、 onCon- nected コールバックが呼ばれてからでないと LocationClient#getLastLocation を呼ぶことができません。 以上をまとめると、リスト 3.19 のような実装になります。 リスト 3.19 : GPS を使うコード public class MainActivity extends Activity implements ConnectionCa11backs , OnConnectionFai1edListener { private LocationC1ient mLocationC1ient ; 72
3.8 センサーのバッチモード これを表にまとめると次のとおりです ( 図 3.13 ) 。 状態 カテゴリ 基本 Accelerotneter Ambient temperature Gyroscope Light Geomagnetic field Proximity ReIative humidity Game rotation ve ( 【 0 「 Geomagnetic 「 05 ⅵ on 0 ( て 0 「 Gravity Orientation Rotation ( tO 「 Gyroscope uncalibrated 説明 相対湿度 近接センサ 気圧センサ 地磁気センサ 照度センサ ジャイロセンサ ( 角速度 ) 周囲の温度 加速度センサ Accelerometer + Gyroscope + Magnetometer Magnetometer Gyroscope AcceIerometer + Gyroscope + Magnetometer Accelerometer + Magnetometer( + G/2S(0四) AcceIerometer + C/2“0P0 Accelerometer + Magnetometer Accelerometer + Gyroscope 連続 変化時 連続 変化時 連続 連続 変化時 変化時 連続 連続 連続 連続 連続 連続 連続 連続 1 回のみ 変化時 特別 Magnetic field uncalibrated Linear acceleration Significant motion Step counter Step detecter 生データ 動き かを示します。 Accelerometer Accelerometer Acceleromete 「 図 3.13 センサーのまとめ トリガーモードとは、センサーの変化をコールバック関数でどのように伝える 63 そこで Android では、センサーのデータを複数回分貯めこんでおき、バッチ処 センサーは非常に便利ですが、使うと消費電力が大きいのがデメリットです。 3.8 センサーのバッチモード また、薄いグレーのセンサーは低消費電力動作可能です。 に呼ばれるので、実際には " 変化時 " と言ってもよさそうです。 は 1 回だけしかコールされません。 " 特別 " となる "Stepdetector" は歩行検知時 ます。 " 変化時 " は変化した時のみ、コールバック関数が呼ばれます。 " 1 回のみ " " 連続 " はセンサーの変化にかかわらず一定の間隔でコールバック関数が呼ばれ
第 3 章センシングデバイス さて、この LocationClient#requestLocationListner を使用する場合は、 com.google.android.gms.location.LocationListener をリスナーにセットし、 コールバックを実装します。これで、更新タイミングでこのコールバックが 呼ばれるようになります。また、リクエストした更新は onPause で解除してお きます ( リスト 3.24 、リスト 3.25 ) 。 リスト 3.24 : Activity への LocationListener の設定 public class MainActivity extends ActivitY implements ConnectionCa11backs' OnConnectionFai1edListener, LocationListener { リスト 3.25 : 位置情報更新のコールバック @Override public void onLocationChanged(Location 10C ) { Toast. makeText(this, "Get Location" , Toast . LENGTH-SHORT) . shov() ; Date date = new Date(10c. getTime() ) ; Simp1eDateFormat sdf = new SimpleDateFormat("MM/dd: HH:mm: ss") ; / / LocationListener を解除 if (mLocationC1ient ! = Ⅱ u11 ) { super. onPause ( ) ; protected void onpause ( ) { @Override mLocation[6] . setText (String. valueOf (10C ・ getBearing() ) ) ; mLocation[5] . setText (String ・ valueOf (10C ・ getAccuracy()) ) ; mLocation[4] . setText (sdf . format (date) ) ; mLocation[3] . setText (String. valueOf ( 10C ・ getSpeed()) ) ; mLocation[2] . setText (String. valueOf ( 10C ・ getA1titude() ) ) ; mLocation[1] . setText (String. valueOf ( 10C ・ getLongitude())) ; mLocation[0] . setText (String. valueOf (10C ・ getLatitude() ) ) ; 今回は取得した Location オプジェクトからいくつかのデータを取り出してい mLocationCIient . disconnect() ; / / Goog1e P1ay Services との切断 mLocationC1ient. removeLocationUpdates (this) ; ます。 78 ・ Longitude : 軽度 ( 度 ) ・ Latitude : 緯度 ( 度 )
method ur 1 requestBody listener errorListener 4.13 ライプラリを使ったネットワーク通信 表 4.3 GET リクエスト 2 行目 リクエストメソッドを指定する アクセスする URL を指定する 工ラーレスポンスリスナー レスポンスリスナー リクエスト時にボディに送る JSONObject を指定する 299 以外 ) の場合に実行されます。 リクエストをリクエストキューに追加すると自動的にバックグラウンドでネッ トワーク通信が行われ、ネットワーク通信が完了すると引数に渡したコールバッ ク (listener 、 errorListener) が実行されます。 4.13.2 レスポンス サーバーのレスポンスが正常系 ( 200 ~ 299 ) だった場合、第 4 引数の listener の コールバックメソッドが実行されます。レスポンスボディは自動的に JSONOb ー ject にパースされ、引数に渡されます ( リスト 4.39 、リスト 4.40 ) 。 リスト 4.39 : 正常系レスポンスリスナー @Override public void onResponse (JSONObj ect j sonObj ect) { Log. d("TEST", json0bject. t0String()); リスト 4.40 : 正常系なレスポンス D/TEST ( 1699 ) : {"users": [ { ” id ” : 1 {"id":2,"gender":"ma1e ” ,"name":"bob"}]} サーバのレスポンスが異常系 ( 200 ~ 299 以外 ) だった場合、第 5 引数の er ー rorListener のコールバックメソッドが実行されます。工ラーの内容は引数の VoIIeyError オプジェクトに人っています ( リスト 4.41 、リスト 4.42 ) 。 川 1
第 3 章センシングデバイス ・ SensorEventListener ・ SensorEvent 使い方としては、 SensorManager をシステムから取得し、使用するセンサーを 指定します。センサーイベントを受け取るように設定すると、 SensorEventLis- tener で設定したリスナーで SensorEvent を受け取れるので、これを解析すると いう流れになります。では具体的に見て行きます。 まずは SensorManager をシステムから取得します ( リスト 3.1) 。 リスト 3.1 : センサーマネージャの取得 private SensorManager mSensorManager ; (SensorManager)getSystemService(Context . SENSOR—SERVICE) ; mSensorManager 例として、 Acceleration ( 加速度センサー ) を取得します ( リスト 3.2 ) 。 リスト 3.2 : センサーの取得 Sensor acceleration mSensorManager. getDefau1tSensor (Sensor. TYPE—ACCELEROMETER) ; 次にセンサーを有効にします ( リスト 3.3 ) 。 リスト 3.3 : センサーの有効化 mSensorManager. registarListener (this , acceleration, Sensor. SENSOR-DELAY-NORMAL) ; これで、該当する Activity に SensorEventListener が設定され、イベントリ スナーが呼ばれるようになります。 SensorEventListener の実装を見ていきましよう。 意します ( リスト 3.4 ) 。 リスト 3.4 : イベントコールバック 44 こではリスナーは 2 つ用
第 5 章 BIuetooth 通信 ・ BIuetooth SMART : BLE でのみ通信可能で、クラシックとの通信はでき ない ・ BIuetooth SMART READY : BLE とクラシックの両方の通信に対応 BLE では GATT (Generic Attribute) というプロファイルで通信を行いま す。 Android アプリケーションで BLE 機器と通信する場合、次の条件が揃って いなければいけません。 ・ Android 端末がハード的に BIuetooth4.0 に対応していること ・ Android OS のバージョンが BLE に対応していること (Android4.3) BLE 機器と通信するアプリケーションの開発で使用する android. bluetooth パッケージ API を紹介します。 5.10.1 BIuet00thManager Android4.3 (API Level 18 ) より、 BluetoothManager クラスがサポートさ れ、 BIuetoothAdapter のインスタンスの取得などができるようになりました ( リスト 5.13 ) 。 リスト 5.13 : BluetoothManager B1uet00thManager manager (B1uetoothManager) getSystemService (Context . BLUETOOTH-SERVICE) ; mB1uet00thAdapter = manager ・ getAdapter() ; 5.10.2 LeScanCaIIback GATT プロファイル対応のデバイスの探索結果を受け取るためのコ クメソッドが定義されたクラスです。 5.10.3 BIuet00thGattCalIback ーノレノヾツ 指定した BLE 機器と接続が完了したときに呼ばれるコールバックメソッドが 定義されたクラスです。 BluetoothGatt クラスのインスタンスを受け取ります。 124
5.4 BIuetooth 対応の外部デバイスの検索 (BIuetoothAdapter) abled メソッドを使用します。 Bluetooth を有効にするにはインテントに「 AC- TION REQUEST_ENABLE 」を指定して startAcitivityForResult メソッド を実行します。 アプリケーションの実行時、システムはユーザに自動で B1uetooth 許可リ クエストダイアログを表示し、ユーザがダイアログのボタンを押下すると onActivityResuIt メソッドがコールバックされます。 Bluetooth が有効になっ た場合は、このメソッドの引数 resultCode に Activity. RESULT ()K が返って きます ( 図 5.1) 。 △ B [ uetooth アクセス権限の要求 アプリケーションが BIuetooth を ON にする許可を求めています。許 可しますか ? いいえ はい 図 5.1 BIuetooth 許可リクエストダイアログ ( 有効設定 ) 5.4 BIuetooth 対応の外部デバイスの検索 (BIuetoothAdapter) アプリケーションから実行中の Android 端末の近隣にある Bluetooth デバイ スを検索するサンプルプログラムについて説明します。デバイス検索を行うに は BIuetoothAdapter クラスの startDiscovery メソッドを使用します ( リスト 5.2 ) 。 リスト 5.2 : デバイス検索 B1uet00thAdapter btAdapter = B1uet00thAdapter. getDefau1tAdapter ( ) ; if (btAdapter. isDiscovering() ) { / / 探索中だったら一度探索をキャンセル btAdapter. cance1Discovery() ; 川 9
第 3 章センシングデバイス ・ SensorEvent. values[()] ・ SensorEvent. values[ll ・ SensorEvent. values[21 : x 軸加速度 : y 軸加速度 : z 軸加速度 加速度なので、そのまま x 、 y 、 x のそれぞれの加速度が取得できます。これを コードで取得するには、 onSensorChanged を次のとおりに変更します ( リスト 3.6 ) 。 リスト 3.6 : センサー値変化イベントコールバック @Override public f inal VOid onSensorChanged (SensorEvent event) { / / センサーの値が変化した場合に呼ばれる float ロ accell = new f10at[3] ; accell [ 0 ] accell [ 1 ] accell [ 2 ] Log. i(TAG, Log. i(TAG, Log. i (TAG, event . values [ 0 ] ; event . values [ 1 ] ; event . values [ 2 ] ; "acce11[X] "accell [Y] "acce11[Z] ” + acce11[2]) ; mSensor [ 0 ] . setText (String. va1ueOf (accell [ 0 ] ) ) ; mSensor [ 1 ] . setText (String. va1ueOf (accell [ 1 ] ) ) ; mSensor [ 2 ] . setText (String. va1ueOf (accell [ 2 ] ) ) ; + acce11[O]); + accell[l]); こではログにセンサー値を表示するようにしています。 実際のデータを取得した例としては次のようなデータが取得できます ( 図 3.4 ) 。 48
第 3 章センシングデバイス @Override protected void onResume() { super. onResume ( ) ; / / センサの取得 List く Sensor> sensors = mSensorManager ・ getSensorList (Sensor. TYPE-ALL) ; / / センサマネージャヘリスナーを登録 sensors) { for (Sensor sensor ただし、取得するデータを処理する場合は、次のように場合分けして処理する sensor , SensorManager. SENSOR—DELAY—UI ) ; mSensorManager. registerListener (this , (sensor. getType() Sensor. TYPE-ACCELEROMETER) { sensor , SensorManager. SENSOR—DELAY—UI ) ; mSensorManager. registerListener (this , (sensor. getType() Sensor. TYPE-PROXIMITY) { if if 50 ます。 場所にオプジェクトを出現させるような AR アプリの作成ができるようになり 見られるように変化させたり、さらに位置情報とカメラを組みわせて、特定の 端末の傾きを利用することで、端末の中のオプジェクトをさまざまな角度から す。なぜなら傾きは方位と加速度を使用して計算する必要があるからです。 複数のセンサーを使用する例として、後述する傾きを取得する場合がありま / / 処理 else if (event. sensor. getType() Sensor. TYPE—PROXIMITY) { / / 値が変化したセンサーが近接センサーだった場合 / / 処理 if (event. sensor. getType ( ) = = Sensor. TYPE-ACCELEROMETER) { / / 値が変化したセンサーが加速度センサーだった場合 public void onSensorChanged(SensorEvent event) { @Override リスト 3.8 : 複数センサー利用時のイベントコールバック 必要があります ( リスト 3.8 ) 。