Android Things 1.0.1で、iBeaconの信号を受信してみる

## 経緯
Android Thingsで、BLEが使えるということなので、iBeaconの信号を受信するコードをkotlinで書いてみました。

## 動作確認環境
・Android Things 1.0.1 for Raspberry pi 3
・Android Studio 3.1.3

## コード
Permissionとして、

android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.ACCESS_FINE_LOCATION

が必要です。

```xml:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.eguchi.android.androidthingstest4">

    <uses-feature android:name="android.hardware.bluetooth_le" />

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>


    <application>
        <uses-library android:name="com.google.android.things" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.IOT_LAUNCHER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```

```kotlin:MainActivity.kt
package jp.eguchi.android.androidthingstest4

// Android Things 1.0.1で、iBeaconの信号を受信してみる
// Progmramed by Kazuyuki Eguchi

import android.app.Activity
import android.bluetooth.BluetoothManager
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanResult
import android.content.Context
import android.os.Bundle
import android.util.Log

class MainActivity : Activity() {

    private val TAG = "debug"
    private lateinit var bluetoothManager: BluetoothManager

    private val mscanReceiver = object : ScanCallback() {
        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)
            Log.d(TAG,"onScanFailed:" + errorCode)
        }

        override fun onScanResult(callbackType: Int, result: ScanResult?) {
            super.onScanResult(callbackType, result)

            val datas = result!!.scanRecord!!.bytes

            if((datas.get(5).compareTo(0x4c) == 0)
                        && (datas.get(6).compareTo(0x00) == 0)
                        && (datas.get(7).compareTo(0x02) == 0)
                        && (datas.get(8).compareTo(0x15) == 0)
            ) {
                var uuid = "%02x".format(datas.get(9)) + "%02x".format(datas.get(10)) + "%02x".format(datas.get(11)) + "%02x".format(datas.get(12))
                uuid = uuid + "-%02x".format(datas.get(13)) + "%02x".format(datas.get(14))
                uuid = uuid + "-%02x".format(datas.get(15)) + "%02x".format(datas.get(16))
                uuid = uuid + "-%02x".format(datas.get(17)) + "%02x".format(datas.get(18))
                uuid = uuid + "-%02x".format(datas.get(19)) + "%02x".format(datas.get(20)) + "%02x".format(datas.get(21)) + "%02x".format(datas.get(22)) + "%02x".format(datas.get(23)) + "%02x".format(datas.get(24))

                val major = "%02x".format(datas.get(25)) + "%02x".format(datas.get(26))
                val minor = "%02x".format(datas.get(27)) + "%02x".format(datas.get(28))

                Log.d(TAG,result.device.address + ",rssi=" + result.rssi + "," + uuid + "," + Integer.parseInt(major,16) + "," + Integer.parseInt(minor,16))
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG,"onCreate()")

        bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        val bluetoothAdapter = bluetoothManager.adapter

        bluetoothAdapter.bluetoothLeScanner.startScan(mscanReceiver)
    }
}
```

## 動作イメージ
```console:logcat
06-11 17:12:33.607 6418-6418/jp.eguchi.android.androidthingstest4 I/InstantRun: starting instant run server: is main process
06-11 17:12:33.663 6418-6418/jp.eguchi.android.androidthingstest4 D/debug: onCreate()
06-11 17:12:33.671 6418-6418/jp.eguchi.android.androidthingstest4 D/BluetoothAdapter: isLeEnabled(): ON
06-11 17:12:33.677 6418-6431/jp.eguchi.android.androidthingstest4 D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=11 mScannerId=0
06-11 17:12:33.951 6418-6418/jp.eguchi.android.androidthingstest4 D/vndksupport: Loading /vendor/lib/hw/android.hardware.graphics.mapper@2.0-impl.so from current namespace instead of sphal namespace.
06-11 17:12:36.348 6418-6418/jp.eguchi.android.androidthingstest4 D/debug: CD:A3:5A:BB:19:82,rssi=-81,b9407f30-f5f8-466e-aff9-25556b57fe6e,2＊＊＊6,3＊＊2
06-11 17:12:41.446 6418-6418/jp.eguchi.android.androidthingstest4 D/debug: ED:4D:1C:58:34:6E,rssi=-74,b9407f30-f5f8-466e-aff9-25556b57fe6e,1***1,3＊＊＊8
06-11 17:12:41.485 6418-6418/jp.eguchi.android.androidthingstest4 D/debug: E9:67:63:C7:4B:BA,rssi=-77,b9407f30-f5f8-466e-aff9-25556b57fe6e,8**1,1***4
```