RxAndroidBleでスキャンする

今までiOSでCoreBluetoothやRxBluetoothを使ってBLE通信を試し、記事にしましたが、Androidではどうやってやるのか気になったのでRxAndroidBleライブラリを使ってスキャンしてみました。

RxAndroidBleをbuild.gradleに追加する

build.gradleにRxAndroidBleを追加します。

追加コード

implementation 'com.polidea.rxandroidble2:rxandroidble:1.7.1'

Manufestにパーミッションを追加する

Bluetoothと位置情報のパーミッションを入れる必要があります。

Bluetooth通信で位置情報を何に使うかは不明ですが、位置情報を入れないとスキャンできないので省略できません。

追加コード

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

スキャン!!!

準備が整ったのでActivityにスキャンの処理を書きます!

スキャンのコード

import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.util.Log
import com.polidea.rxandroidble2.RxBleClient
import com.polidea.rxandroidble2.scan.ScanSettings


class MainActivity : AppCompatActivity() {

    private val SYSTEM_LOCATION_PERMISSION_REQUEST_CODE = 4444

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        /**
         * おそらくこのクライアントがBle通信におけるセントラルの役割を果たしている
         */
        val rxBleClient = RxBleClient.create(this)

        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        val REQUEST_ENABLE_BT = 1
        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
        
        //位置情報のパーミッション
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION),
            SYSTEM_LOCATION_PERMISSION_REQUEST_CODE
        )

        //スキャン
        val scanSubscription = rxBleClient.scanBleDevices(
            ScanSettings.Builder().build()
        ).filter {
            it.scanRecord.deviceName != null
        }.subscribe({scanResult ->
            Log.i("ScanDevice:",scanResult.scanRecord.deviceName)
        },{throwable ->
            Log.i("error","$throwable")
        })
    }
}

Ble通信でIOTデバイスを動かしたりする際ほぼ100%名前がついていると思うので名前で絞りましたが、このfilterをなくせば名前のないデバイスがたくさん検出できるのでデバイスを持ってなくても確認できます!

importするライブラリ間違えやすいので気をつけてください!