Android
BluetoothとBluetooth LE API
サーチ…
備考
Bluetooth Classicは、Android 2.0(APIレベル5)以上でご利用いただけます。 Bluetooth LEは、Android 4.3(APIレベル18)以上からご利用いただけます。
アクセス許可
アプリケーションでBluetooth機能を使用するには、この権限をマニフェストファイルに追加します。
<uses-permission android:name="android.permission.BLUETOOTH" />
デバイスの検出を開始したり、Bluetooth設定を操作する必要がある場合は、次の権限も追加する必要があります。
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
Android APIレベル23以上をターゲティングするには、位置情報のアクセスが必要です。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- OR -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
*権限を適切に使用する方法の詳細については、 権限のトピックを参照してください。
Bluetoothが有効になっているかどうかを確認する
private static final int REQUEST_ENABLE_BT = 1; // Unique request code
BluetoothAdapter mBluetoothAdapter;
// ...
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
// ...
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
// Bluetooth was enabled
} else if (resultCode == RESULT_CANCELED) {
// Bluetooth was not enabled
}
}
}
デバイスを発見可能にする
private static final int REQUEST_DISCOVERABLE_BT = 2; // Unique request code
private static final int DISCOVERABLE_DURATION = 120; // Discoverable duration time in seconds
// 0 means always discoverable
// maximum value is 3600
// ...
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, DISCOVERABLE_DURATION);
startActivityForResult(discoverableIntent, REQUEST_DISCOVERABLE_BT);
// ...
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_DISCOVERABLE_BT) {
if (resultCode == RESULT_OK) {
// Device is discoverable
} else if (resultCode == RESULT_CANCELED) {
// Device is not discoverable
}
}
}
近くのBluetoothデバイスを探す
最初にBluetoothAdapter
宣言しBluetoothAdapter
。
BluetoothAdapter mBluetoothAdapter;
次に、 ACTION_FOUND
用のBroadcastReceiver
を作成します。
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//Device found
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a list
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
BroadcastReceiver
登録する
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
次に、 startDiscovery
を呼び出して、近くのBluetoothデバイスの検出を開始します
mBluetoothAdapter.startDiscovery();
登録を解除することを忘れないでくださいBroadcastReceiver
内側にonDestroy
unregisterReceiver(mReceiver);
Bluetoothデバイスに接続する
BluetoothDeviceを入手したら、それと通信できます。ソケット入出力\出力ストリームを使って行われるこの種の通信:
これらは、Bluetooth通信の確立のための基本的な手順です。
1)ソケットを初期化する:
private BluetoothSocket _socket;
//...
public InitializeSocket(BluetoothDevice device){
try {
_socket = device.createRfcommSocketToServiceRecord(<Your app UDID>);
} catch (IOException e) {
//Error
}
}
2)ソケットに接続する:
try {
_socket.connect();
} catch (IOException connEx) {
try {
_socket.close();
} catch (IOException closeException) {
//Error
}
}
if (_socket != null && _socket.isConnected()) {
//Socket is connected, now we can obtain our IO streams
}
3)ソケット入力/出力ストリームの取得
private InputStream _inStream;
private OutputStream _outStream;
//....
try {
_inStream = _socket.getInputStream();
_outStream = _socket.getOutputStream();
} catch (IOException e) {
//Error
}
入力ストリーム - 入力データチャネルとして使用されます(接続デバイスからのデータ受信)
出力ストリーム - 送信データチャネルとして使用(接続デバイスにデータを送信)
3番目のステップが終了すると、以前に初期化されたストリームを使用して、両方のデバイス間でデータを送受信できます。
1)受信データ(ソケット入力ストリームからの読み込み)
byte[] buffer = new byte[1024]; // buffer (our data)
int bytesCount; // amount of read bytes
while (true) {
try {
//reading data from input stream
bytesCount = _inStream.read(buffer);
if(buffer != null && bytesCount > 0)
{
//Parse received bytes
}
} catch (IOException e) {
//Error
}
}
2)データの送信(出力ストリームへの書き込み)
public void write(byte[] bytes) {
try {
_outStream.write(bytes);
} catch (IOException e) {
//Error
}
}
- もちろん、接続、読み書き機能は専用のスレッドで行う必要があります。
- ソケットとストリームオブジェクトが必要です
近くのBluetooth低エネルギーデバイスを見つける
しかし、デバイスのスキャン方法はAPI 21で変更されています。デバイスの検索は、スキャンするサービスUUID (公式に採用されている16ビットUUIDまたは独自仕様のもの)を定義することから始める必要があります。 。この例では、APIをBLEデバイスを検索するための独立した方法を示します。
- Bluetoothデバイスモデルを作成する:
public class BTDevice {
String address;
String name;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- Bluetoothスキャンインターフェイスを定義する:
public interface ScanningAdapter {
void startScanning(String name, String[] uuids);
void stopScanning();
List<BTDevice> getFoundDeviceList();
}
- スキャンファクトリクラスを作成する:
public class BluetoothScanningFactory implements ScanningAdapter {
private ScanningAdapter mScanningAdapter;
public BluetoothScanningFactory() {
if (isNewerAPI()) {
mScanningAdapter = new LollipopBluetoothLEScanAdapter();
} else {
mScanningAdapter = new JellyBeanBluetoothLEScanAdapter();
}
}
private boolean isNewerAPI() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}
@Override
public void startScanning(String[] uuids) {
mScanningAdapter.startScanning(uuids);
}
@Override
public void stopScanning() {
mScanningAdapter.stopScanning();
}
@Override
public List<BTDevice> getFoundDeviceList() {
return mScanningAdapter.getFoundDeviceList();
}
}
- 各APIのファクトリ実装を作成する:
API 18:
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.os.Build;
import android.os.Parcelable;
import android.util.Log;
import bluetooth.model.BTDevice;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class JellyBeanBluetoothLEScanAdapter implements ScanningAdapter{
BluetoothAdapter bluetoothAdapter;
ScanCallback mCallback;
List<BTDevice> mBluetoothDeviceList;
public JellyBeanBluetoothLEScanAdapter() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mCallback = new ScanCallback();
mBluetoothDeviceList = new ArrayList<>();
}
@Override
public void startScanning(String[] uuids) {
if (uuids == null || uuids.length == 0) {
return;
}
UUID[] uuidList = createUUIDList(uuids);
bluetoothAdapter.startLeScan(uuidList, mCallback);
}
private UUID[] createUUIDList(String[] uuids) {
UUID[] uuidList = new UUID[uuids.length];
for (int i = 0 ; i < uuids.length ; ++i) {
String uuid = uuids[i];
if (uuid == null) {
continue;
}
uuidList[i] = UUID.fromString(uuid);
}
return uuidList;
}
@Override
public void stopScanning() {
bluetoothAdapter.stopLeScan(mCallback);
}
@Override
public List<BTDevice> getFoundDeviceList() {
return mBluetoothDeviceList;
}
private class ScanCallback implements BluetoothAdapter.LeScanCallback {
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
if (isAlreadyAdded(device)) {
return;
}
BTDevice btDevice = new BTDevice();
btDevice.setName(new String(device.getName()));
btDevice.setAddress(device.getAddress());
mBluetoothDeviceList.add(btDevice);
Log.d("Bluetooth discovery", device.getName() + " " + device.getAddress());
Parcelable[] uuids = device.getUuids();
String uuid = "";
if (uuids != null) {
for (Parcelable ep : uuids) {
uuid += ep + " ";
}
Log.d("Bluetooth discovery", device.getName() + " " + device.getAddress() + " " + uuid);
}
}
private boolean isAlreadyAdded(BluetoothDevice bluetoothDevice) {
for (BTDevice device : mBluetoothDeviceList) {
String alreadyAddedDeviceMACAddress = device.getAddress();
String newDeviceMACAddress = bluetoothDevice.getAddress();
if (alreadyAddedDeviceMACAddress.equals(newDeviceMACAddress)) {
return true;
}
}
return false;
}
}
}
API 21:
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.os.Build;
import android.os.ParcelUuid;
import bluetooth.model.BTDevice;
import java.util.ArrayList;
import java.util.List;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class LollipopBluetoothLEScanAdapter implements ScanningAdapter {
BluetoothLeScanner bluetoothLeScanner;
ScanCallback mCallback;
List<BTDevice> mBluetoothDeviceList;
public LollipopBluetoothLEScanAdapter() {
bluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
mCallback = new ScanCallback();
mBluetoothDeviceList = new ArrayList<>();
}
@Override
public void startScanning(String[] uuids) {
if (uuids == null || uuids.length == 0) {
return;
}
List<ScanFilter> filterList = createScanFilterList(uuids);
ScanSettings scanSettings = createScanSettings();
bluetoothLeScanner.startScan(filterList, scanSettings, mCallback);
}
private List<ScanFilter> createScanFilterList(String[] uuids) {
List<ScanFilter> filterList = new ArrayList<>();
for (String uuid : uuids) {
ScanFilter filter = new ScanFilter.Builder()
.setServiceUuid(ParcelUuid.fromString(uuid))
.build();
filterList.add(filter);
};
return filterList;
}
private ScanSettings createScanSettings() {
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
.build();
return settings;
}
@Override
public void stopScanning() {
bluetoothLeScanner.stopScan(mCallback);
}
@Override
public List<BTDevice> getFoundDeviceList() {
return mBluetoothDeviceList;
}
public class ScanCallback extends android.bluetooth.le.ScanCallback {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
if (result == null) {
return;
}
BTDevice device = new BTDevice();
device.setAddress(result.getDevice().getAddress());
device.setName(new StringBuffer(result.getScanRecord().getDeviceName()).toString());
if (device == null || device.getAddress() == null) {
return;
}
if (isAlreadyAdded(device)) {
return;
}
mBluetoothDeviceList.add(device);
}
private boolean isAlreadyAdded(BTDevice bluetoothDevice) {
for (BTDevice device : mBluetoothDeviceList) {
String alreadyAddedDeviceMACAddress = device.getAddress();
String newDeviceMACAddress = bluetoothDevice.getAddress();
if (alreadyAddedDeviceMACAddress.equals(newDeviceMACAddress)) {
return true;
}
}
return false;
}
}
}
呼び出してデバイスのリストを取得する:
scanningFactory.startScanning({uuidlist}); wait few seconds... List<BTDevice> bluetoothDeviceList = scanningFactory.getFoundDeviceList();