前:ScalaでAndroidアプリを作る


iBeaconをAndroidで読んで、ビーコンが現れたらNotificationを出すとかできるライブラリを作った。
advertiseパケットを自前でparseしてiOSのSDKで使われてるのと同じフォーマットの16進コードに変換してるけど、scalaなので15行ぐらいで書けた。

https://github.com/shokai/iBeacon-AndroidScala

先週研究会でspammerっていう人がiBeaconの仕組みとかをまとめて発表してくれた。
へぇーと思ったのでMyBeacon買って土日にAndroid用のライブラリを作った。

Javaは冗長でつらいのでScalaで書いたけど、Scalaもライブラリの配信方法が.classをjarに固めてmaven使うとか冗長でつらい。どうすればいいんだ。なんでコンパイル前のscalaスクリプトのまま流通させないのか理解できない。


使い方


詳しくはGitHubのREADMEに書いた。

Activityから起動する例
import org.shokai.ibeacon.{IBeacon, Beacon};

class MainActivity extends Activity{

lazy val iBeacon:IBeacon = new IBeacon(this)

override def onCreate(savedInstanceState:Bundle){

// ビーコンを発見した時にcallbackされる
iBeacon.onDiscover((beacon:Beacon) =>
Log.v("iBeacon", s"UUID=${beacon.uuid} Major=${beacon.major} Minor=${beacon.minor} RSSI=${beacon.rssi}")
)

}

}


AndroidManifest.xml
<manifest>
<application> ~~ (略) ~~ </application>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
</manifest>

とても簡単でよい。
onBeaconというコールバックもあって、これは全てのビーコンパケットをコールバックしてくる。
ビーコンは常に電波を発信しまくっているので、onBeaconイベントはものすごい勢いで呼ばれる。
コールバックされるBeaconオブジェクトのrssiプロパティで受信信号強度が取れるので、距離もなんとなく計れる。
だいたい見通し25メートルぐらいで-90、接触するぐらい近いと-20〜-10とかになる。

なお1度呼ばれた同じビーコンのonDiscoverが再び呼ばれるのは、そのビーコンの信号が5秒間無くなって再び現れた時。


サンプルアプリ


信号を読むやつapk


ビーコンを見つけたら通知を出すサービス(電源ONしたら自動起動する)

これ改造すると、猫にビーコンつけて近寄ってきたらエサくれ通知を出すとか、自分が家に近づいたらカギが開くとか簡単に作れる。


iBeaconとは

Appleが考えたBluetoothデバイスの存在通知手法で、ずっと電波出し続けているデバイス(ビーコン)をいろいろな場所に設置しておいて、その電波をスマホが検知すると「〜〜というデバイスがあるのでアプリを起動しますか?」のような通知を出す。
最近のiOSアプリ持ってないので実物を見たことがないんだけどそんな感じのはず。

実装としてはBluetooth LE (ローエナジー) のadvertiseパケットの末尾にビーコンのUUIDやmajor,minorといった識別子を突っ込んでいるもので、そんなに凄い事をしているわけではない。
なのでAndroidでもadvertiseパケットを見て、バイナリをparseしたらUUIDとか取り出せた。

インスタントメッセンジャーアプリの名前欄で会話してる人とかいるけど、そういうのに近い。


1800円のMyBeaconを3個買って、研究室に設置した。


参考

iOS – AndroidでiBeacon信号を受信してみよう – Qiita