RxAndroidBleでwriteしてみた

はじめに

iOS, React NativeのBluetoothライブラリをこの頃触っていますがAndroidをサボりがちだったので久々に触ってみました。

以前RxAndroidBleでスキャンするという記事を書きました。あれから約半年ぶりにRxAndroidBleを触ってみました。

Connect

公式のREADMEを読むと以下のように使うみたいです。

Disposable disposable = device.establishConnection(false) // <-- autoConnect flag
    .subscribe(
        rxBleConnection -> {
            // All GATT operations are done through the rxBleConnection.
        },
        throwable -> {
            // Handle an error here.
        }
    );

// When done... dispose and forget about connection teardown :)
disposable.dispose();

スキャンして見つけたデバイスに対してestablishConnectionすればつながります。

Write

Writeの前にKotlinわからなすぎてByteArrayの作成方法でつまづいたのでまとめます。

Bluetoothデバイスに対して0x01, 0x02などのByteArrayをwriteするわけですが、一発でByteArrayを作ることはできず以下のキャストを行います。

val writeData = arrayOf(0x01, 0x02).map(Int::toByte).toByteArray()

スキャンから繋げて以下のようなコードでwriteすることができます。上記で解説したByteArray配列とwrite可能なcharacteristicを用意しておけば大丈夫です。

iOSのwithResponse, withoutResponseなどの概念は私が調べた限りで見当たりませんでした。どっちもwriteCharacteristic()を使えばいけちゃいそうです。

val scanSubscription = rxBleClient.scanBleDevices(
            ScanSettings.Builder().build()
        ).filter {
            it.scanRecord.deviceName == "toio Core Cube"
        }.switchMap {
            it.bleDevice.establishConnection(false)
        }.flatMapSingle {
            it.writeCharacteristic(uuid, writeData)
        }.subscribe({device ->
            Log.d("connect", "成功")
        },{throwable ->
            Log.i("error","$throwable")
        })

コード一覧

検証用デバイスはsonyが発売しているtoio core cubeを使用しています。

iosだけですがコントローラアプリを出しているのでよかったらダウンロードしてみてください。

mport 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.RxBleDevice
import com.polidea.rxandroidble2.scan.ScanSettings
import java.util.*

class MainActivity : AppCompatActivity() {
    private val SYSTEM_LOCATION_PERMISSION_REQUEST_CODE = 4444

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

        val rxBleClient = RxBleClient.create(this)
        var device: RxBleDevice? = null


        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 uuid = UUID.fromString("10B20104-5B3B-4571-9508-CF3EFCD7BBAE")
        val writeData = arrayOf(0x03, 0x00, 0x03, 0x3F, 0x40, 0x7F, 0x3F, 0xFF, 0x1E, 0x01, 0xFF, 0x7F).map(Int::toByte).toByteArray()

        //スキャン
        val scanSubscription = rxBleClient.scanBleDevices(
            ScanSettings.Builder().build()

        ).filter {
            it.scanRecord.deviceName == "toio Core Cube"
        }.switchMap {
            it.bleDevice.establishConnection(false)
        }.flatMapSingle {
            it.writeCharacteristic(uuid, writeData)
        }.subscribe({device ->
            Log.d("connect", "成功")
        },{throwable ->
            Log.i("error","$throwable")
        })
    }
}