こんにちはKID.Aです。
今回もBLEの記事になります。
Android 5.0からBluetoothLeScannerというクラスが追加になり、BLEデバイスの検索やフィルターが簡単に実装できるようになりましたので実装方法を紹介していこうとおもいます。
下記はBluetoothLeScannerのAPIのリンクになります。
・開発サイトのAPI
http://developer.android.com/intl/ja/reference/android/bluetooth/le/BluetoothLeScanner.html
それでは実装をしていきます。
マニフェストに追加
AndroidManifest.xmlに以下を追加します。
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
実装
BluetoothLeScannerで周辺のデバイスを検索、フィルターするソースを記載します。
※ソースはシンプルにしています。start_buttonでスキャンを開始して、stop_buttonでスキャンを終了しています。
package jp.co.bluetoothle; import android.Manifest; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; import android.content.Context; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter adapter = manager.getAdapter(); final BluetoothLeScanner bluetoothLeScanner = adapter.getBluetoothLeScanner(); // 6.0以降はコメントアウトした処理をしないと初回はパーミッションがOFFになっています。 // requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 0); final ScanCallback scanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); Log.d(MainActivity.class.getName(), "callbackType = " + callbackType); BluetoothDevice bluetoothDevice = result.getDevice(); Log.d(MainActivity.class.getName(), "address:" + bluetoothDevice.getAddress()); Log.d(MainActivity.class.getName(), "name:" + bluetoothDevice.getName()); } @Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); } @Override public void onScanFailed(int errorCode) { super.onScanFailed(errorCode); } }; findViewById(R.id.start_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ScanFilter scanFilter = new ScanFilter.Builder() .setDeviceName("DeviceName") .build(); ArrayList scanFilterList = new ArrayList(); scanFilterList.add(scanFilter); ScanSettings scanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_BALANCED) bluetoothLeScanner.startScan(scanFilterList, scanSettings, scanCallback); } }); findViewById(R.id.stop_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { bluetoothLeScanner.stopScan(scanCallback); } }); } }
BluetoothLeScanner#startScanでスキャンを開始できます。
BluetoothLeScanner#startScanにScanFilterのリストとScanSettingsを引数に追加することで検索条件のフィルターを設定できます。
ソースでは、ScanFilterでデバイス名が”DeviceName”と一致する検索結果をフィルターしています。またScanSettingsでScanModeの設定をしています。
スキャン結果はScanCallBack#onScanResultにcallbackType(CALLBACK_TYPE_ALL_MATCHES、CALLBACK_TYPE_FIRST_MATCH、CALLBACK_TYPE_MATCH_LOST)とScanResultが通知されます。
BluetoothAdapter.LeScanCallback#onLeScanはデバイスを取得できた(アドバタイジングをうけた)タイミングで呼ばれます。アドバタイジングは一定間隔で常に発行されているため一定間隔でBluetoothAdapter.LeScanCallback#onLeScanが呼ばれ続ける挙動になります。これと同じくBluetoothLeScanner#startScanの後、デバイスを取得できたタイミングでScanCallBack#onScanResultが呼ばれ続けます。
ScanResult#getDeviceでBluetoothDeviceを取得します。
BluetoothDeviceが取得できれば、この記事と同じBluetoothAdapter.LeScanCallback#onLeScanが呼ばれたあとの処理と同じに実装すればペリフェラル側と接続できます。
BluetoothLeScanner#stopScanでスキャンを停止できます。引数のBluetoothAdapter.LeScanCallbackはBluetoothLeScanner#startScanで設定した変数を渡さないと停止しないので注意してください。
4.4まではstartActivityForResultを行ったり、スキャン条件を自分で実装しなければいけなかったのですが、BluetoothLeScannerになってこのへんが簡単になりました。
以上です。