こんにちは株式会社ドラプロの「おひろ」といいます。
iOS/Androidエンジニアやってます。
初ブログです。今後ともよろしくお願いいたします。
研究のために先日会社でiBeaconを購入しました。
こちら
Androidでも4.3以降であればビーコンの信号を受信できるみたいだったので、
試しにコードを書いてみました。その概要をまとめましたので公開します。
さらに最近Android Wearも手に入れたので、それとも連携させてみました。
iBeaconからの信号→Android端末で受け取る→Wearに通知してWear上でメッセージ表示、
という流れの簡単なサンプルアプリを作りました。
WearでiBeaconからの信号を直接受けることも可能みたいですが、
あまりやらない方がいい的な記事を見かけたりしたのでAndroid端末をかましています。
まずiBeaconからの信号を受信する方法ですが、Manifestファイルに
Bluetooth通信を許可するパーミッションの設定を行います。
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
次にソースコード側で以下のパッケージをimportします。
import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice;
これらのAPIが4.3以降に導入されたものなので、それ以前では実装できないようです。
次に監視を開始したいタイミングで以下のコードを書きます。
今回はひとまずonCreateで呼びました。
BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); bluetoothAdapter.startLeScan(this);
ビーコンを発見したときに通知を受け取るために、BluetoothAdapter.LeScanCallbackを実装します。
public class MyActivity extends Activity implements BluetoothAdapter.LeScanCallback { : : @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // ビーコンが発見されるたびにこのメソッドがコールされるので、 // 受信したデータをもとにやりたいことをここに書く } : : }
第三引数のscanRecordのbyte配列に受信したデータが以下の並びで入っています。
Byte 数 | 説明 |
---|---|
1 | 1 ブロック目のバイト数 |
2,3 | flag |
4 | 2 ブロック目のバイト数 |
5 | メーカー固有の AD type データ |
6,7 | 会社コード(0x004C が Apple の会社コード) |
8 | データのタイプ(0×02 が iBeacon) |
9 | 連なる iBeacon データのバイト数 |
10~25 | UUID |
26,27 | major |
28,29 | minor |
30 | 校正された電波強度(距離を求めるときの基準値、2 の補数) |
これを元にUUIDやmajar値などを取り出して、ビーコンの判別をすることができます。
*データの並びや、取り出し方に関しては、このページを参考にさせていただきました。
ひとまずAndroid端末にいくつか受信したパラメータを表示してみました。
画像のintensityと表示されている部分は第二引数のrssiの値を表示したものです。
rssiは受信した電波の強度を表す数値で、ビーコンとの距離が近くなるほど数値が大きくなります。
今回は閾値を設け、このrssiがその閾値を超えたときにWearに通知を送りました。
つまり、閾値を超えた=ビーコンのあるエリアに入った、と見なして通知を送る訳です。
Wearへ通知メッセージを送るために、以下のパッケージをimportします。
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationManagerCompat;
通知を行いたい箇所で以下のコードを書きます。
// 通知する内容を構築するビルダー生成 NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this); // ----- 最低限必要な情報 ------- notificationBuilder.setSmallIcon(R.drawable.dorapro); // アイコン画像 notificationBuilder.setContentTitle("通知"); // タイトル notificationBuilder.setContentText("ビーコン発見!"); // メッセージ内容 // ---------------------------- // バイブレーションさせたい場合に設定する notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE); // 通知を送るためのノティフィケーションマネージャーの生成 NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); // 通知を送る int notificationId = 1; notificationManager.notify(notificationId, notificationBuilder.build());
これでこんな感じにWearに通知が表示されます。
実際の場面ではWearに通知を送るだけでなく、端末で詳細な情報を見たいことがあると思います。
例えば、お店でクーポンを配布したい時。
お店に入ったときにクーポンが配信されたことのみをWearに通知して、
クーポンの詳細な情報(内容、利用場所、有効期限など)を見たい場合には端末で開く、といったケースが考えられます。
その場合には通知を送る前に以下のコードを追加します。
// Wearから「端末で開く」をタップしたときに開きたいActivityを設定する Intent viewIntent = new Intent(this, MyActivity.class); // 「MyActivity」を開く PendingIntent viewPendingIntent = PendingIntent.getActivity(this, 0, viewIntent, 0); notificationBuilder.setContentIntent(viewPendingIntent);
PendingIntentという特別なIntentを仕込んでおくと、通知したときに以下のように
通知をスワイプすると「端末で開く」という項目が出てきます。
これをタップするとIntent生成時に指定したActivityが開く、という仕組みです。
実装の流れは以上です。結構簡単に実装できるようになってるかと思います。
あとはiBeaconやWearを効果的に使うアイデアがあれば面白いものが作れそうです。
そんなアイデアをお持ちのアナタ。
ドラプロまでお気軽にご連絡ください、お待ちしております(笑)
ではでは。
この記事を書いた人
- ドラプロのアプリ開発チーム、iOS/Androidエンジニアです。 ビールと天満が好きです。
この投稿者の最近の記事
- Arduino2016.04.28ReMINEの開発が進んできたのでいろいろ報告します!
- iOS2016.04.21MIDIとはなんぞやというのをアプリプログラマ的に説明してみる
- Arduino2016.04.12マイコンモジュールの入出力を増やす技を身につけたので言わせてください
- Android2016.04.07BLE経由で組み込みソフトのアップデートができるなんてそんな夢みたいな話…あったわ!