LoginSignup
21
22

More than 1 year has passed since last update.

Android Bluetooth Low Energy

Last updated at Posted at 2020-03-13

仕事でBluetooth Low Energyを使用したのでまとめ

Bluetooth Low Energy(BLE)とは

Bluetooth Low Energy の概要からの引用。
Bluetooth Low Energy(BLE)は、クラシック Bluetooth と比較して、消費電力を大幅に抑えた設計となっています。そのおかげで Android アプリが、近接センサー、心拍数モニター、フィットネス端末など電力要件が厳しい BLE 端末と通信することが可能になっています。

Bluetooth Low Energy(BLE)ドキュメント

Androidデベロッパー向けのドキュメントのBluetooth Low Energy の概要を確認。

Bluetooth Low Energy(BLE)の参考コード

Androidでの使用方法はAndroidの中に存在する可能性が高いです。そのためAOSPを確認します。

上記内にBLEを使用するための参考コードがあるので参照してください。
ここでは参考コードの解説はしません。

Bluetooth Low Energy(BLE)の実装方法

パーミッションの追加

BLEを使用するためには次の3つのパーミッションを追加する必要がある。

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

<!-- If your app targets Android 9 or lower, you can declare
     ACCESS_COARSE_LOCATION instead. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

上記パーミッションにはアプリの権限をリクエストする必要があるものが含まれます。
権限のリクエスト方法はアプリの権限をリクエストするを参照してください。

インストールの制限

次の宣言を記述するとBLEサポート端末のみしかインストール出来なくなります。BLE必須の場合は宣言しても良いとは思います。BLEはあくまでも一部の機能である場合は,後述する方法でBLEサポート端末化を確認可能。

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

BLE のセットアップ

BluetoothのアクティビティにはBluetoothAdapterが必要なため,BluetoothAdapterを取得する方法を記載します。

BluetoothAdapterを取得する

BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();

BLEサポート端末か確認

  1. bluetoothManager.getAdapter()がnullの場合Bluetoothはサポートされていません。
  2. PackageManager.hasSystemFeature()BLEを使用可能か判断
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    // BLE not supported
}

BluetoothのON,OFF確認

bluetoothAdapter.isEnabled()BluetoothのON,OFF確認を行いOFFの場合は,ONに変更してもらう必要があります。

例:BluetoothをONに切り替えてもらうためのインテント発行方法

Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_ENABLE_BT);

BLE 端末の検出

BLEデバイスを検索するにはBluetoothLeScannerのインスタンスを取得する必要があります。
次のようにしてBluetoothLeScannerを取得します。

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothLeScanner bleScanner bluetoothAdapter.getBluetoothLeScanner();

BluetoothLeScannerstartScan()メソッドを使用する事でBLEデバイスの検索を行えます。

bleScanner.startScan(buildScanFilters(), buildScanSettings(), callback);

startScan()メソッドへ渡すためのList<ScanFilter>ScanSettingsは下記のようにして設定します。

    /**
     * Return a List of {@link android.bluetooth.le.ScanFilter} objects to filter by Service UUID.
     */
    private List<ScanFilter> buildScanFilters() {
        List<ScanFilter> scanFilters = new ArrayList<>();

        ScanFilter.Builder builder = new ScanFilter.Builder();
        // Comment out the below line to see all BLE devices around you
        builder.setServiceUuid(null);
        scanFilters.add(builder.build());

        return scanFilters;
    }

    /**
     * Return a {@link android.bluetooth.le.ScanSettings} object set to use low power (to preserve
     * battery life).
     */
    private ScanSettings buildScanSettings() {
        ScanSettings.Builder builder = new ScanSettings.Builder();
        builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
        return builder.build();
    }

startScan()メソッドへ渡すためのコールバックは下記のように記述します。
対象のBLE端末がスキャンされるたびにonScanResult()が呼び出されます。

/**
 * Helper class for BLE scan callback.
 */
public class BleScanCallback extends ScanCallback {
    private Set<ScanResult> mResults = new HashSet<>();
    private List<ScanResult> mBatchScanResults = new ArrayList<>();

    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
            mResults.add(result);
        }
    }

    @Override
    public void onBatchScanResults(List<ScanResult> results) {
        // In case onBatchScanResults are called due to buffer full, we want to collect all
        // scan results.
        mBatchScanResults.addAll(results);
    }
}

GATTサーバーへの接続(BLE端末への接続)

BLE端末に接続すること、厳密に言うと、BLE端末上の GATTサーバーに接続することです。BLE端末上の GATTサーバーに接続するには、BluetoothDeviceconnectGatt()メソッドを使用します。
BluetoothDeviceのインスタンスは次のように取得します。

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);

GATTサーバーへの接続は次のように行います。

BluetoothGatt gatt = device.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE)

connectGatt()メソッドへ渡すためのコールバックは下記のように記述します。

public class BleGattCallback extends BluetoothGattCallback {
    /**
     * {@inheritDoc}
     */
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic,
            int status) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic,
            int status) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic) {
    }
}
  • onConnectionStateChange:接続・切断の際に呼び出されます。接続時はdiscoverServices()メソッドを呼びます。
  • onServicesDiscovered:接続時にdiscoverServices()メソッドを呼び出すと、完了後にこのメソッドが呼び出されます。この後、BLEからの通知を受け取るためのUUIDの登録やMtuの値変更などすると良いです。
  • onCharacteristicWrite:BLEデバイスに向けてAndroidからメッセージを送る(Write)と書き込み完了としてonCharacteristicWriteが呼び出されるようです。
  • onCharacteristicChanged:BLEデバイスからAndroidへメッセージが送られるとこのメソッドが呼び出されます。どのUUIDからメッセージが送られたのかを確認して適切な処理を行うのが良いでしょう。

GATTサーバーの切断(BLE端末の切断)

connectGatt()メソッド呼び出しで受け取ったBluetoothGattdisconnect()メソッドを呼び出すと切断できます。終了する際は、close()メソッドも呼び出しておくと良いでしょう。

gatt.disconnect();
gatt.close();

その他注意点

  1. onCharacteristicChanged()メソッドでBLEからメッセージを受け取って、BLEデバイスに何か値を返却するなどあると思いますが、onCharacteristicChanged()のスレッド内(処理内)でBLEデバイスに書き込むのは非常に危険です。別スレッド(メインスレッド)から書き込みましょう。
  2. BLEデバイスに対して書き込みを連続で行うのは非常に危険です。書き込んだらその都度onCharacteristicWrite()メソッドの書き込み完了を待ちましょう。

サンプルコード

  • Java版

  • Kotlin版

内容はBLEデバイスをスキャンして、選んだBLEに接続するだけのシンプルなものになります。

21
22
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
22