Last active
August 29, 2015 14:19
-
-
Save YukiMatsumura/7c6c6bb92539254024e6 to your computer and use it in GitHub Desktop.
Bluetooth Low Energy ref: http://qiita.com/Yuki_312/items/0ab49dfa9820e1b89cac
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<uses-permission android:name="android.permission.BLUETOOTH"/> | |
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Handles various events fired by the Service. | |
// ACTION_GATT_CONNECTED: connected to a GATT server. | |
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server. | |
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services. | |
// ACTION_DATA_AVAILABLE: received data from the device. This can be a | |
// result of read or notification operations. | |
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
final String action = intent.getAction(); | |
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { | |
mConnected = true; | |
updateConnectionState(R.string.connected); | |
invalidateOptionsMenu(); | |
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { | |
mConnected = false; | |
updateConnectionState(R.string.disconnected); | |
invalidateOptionsMenu(); | |
clearUI(); | |
} else if (BluetoothLeService. | |
ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { | |
// Show all the supported services and characteristics on the | |
// user interface. | |
displayGattServices(mBluetoothLeService.getSupportedGattServices()); | |
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { | |
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); | |
} | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DeviceControlActivity extends Activity { | |
... | |
// Demonstrates how to iterate through the supported GATT | |
// Services/Characteristics. | |
// In this sample, we populate the data structure that is bound to the | |
// ExpandableListView on the UI. | |
private void displayGattServices(List<BluetoothGattService> gattServices) { | |
if (gattServices == null) return; | |
String uuid = null; | |
String unknownServiceString = getResources(). | |
getString(R.string.unknown_service); | |
String unknownCharaString = getResources(). | |
getString(R.string.unknown_characteristic); | |
ArrayList<HashMap<String, String>> gattServiceData = | |
new ArrayList<HashMap<String, String>>(); | |
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData | |
= new ArrayList<ArrayList<HashMap<String, String>>>(); | |
mGattCharacteristics = | |
new ArrayList<ArrayList<BluetoothGattCharacteristic>>(); | |
// Loops through available GATT Services. | |
for (BluetoothGattService gattService : gattServices) { | |
HashMap<String, String> currentServiceData = | |
new HashMap<String, String>(); | |
uuid = gattService.getUuid().toString(); | |
currentServiceData.put( | |
LIST_NAME, SampleGattAttributes. | |
lookup(uuid, unknownServiceString)); | |
currentServiceData.put(LIST_UUID, uuid); | |
gattServiceData.add(currentServiceData); | |
ArrayList<HashMap<String, String>> gattCharacteristicGroupData = | |
new ArrayList<HashMap<String, String>>(); | |
List<BluetoothGattCharacteristic> gattCharacteristics = | |
gattService.getCharacteristics(); | |
ArrayList<BluetoothGattCharacteristic> charas = | |
new ArrayList<BluetoothGattCharacteristic>(); | |
// Loops through available Characteristics. | |
for (BluetoothGattCharacteristic gattCharacteristic : | |
gattCharacteristics) { | |
charas.add(gattCharacteristic); | |
HashMap<String, String> currentCharaData = | |
new HashMap<String, String>(); | |
uuid = gattCharacteristic.getUuid().toString(); | |
currentCharaData.put( | |
LIST_NAME, SampleGattAttributes.lookup(uuid, | |
unknownCharaString)); | |
currentCharaData.put(LIST_UUID, uuid); | |
gattCharacteristicGroupData.add(currentCharaData); | |
} | |
mGattCharacteristics.add(charas); | |
gattCharacteristicData.add(gattCharacteristicGroupData); | |
} | |
... | |
} | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private BluetoothGatt mBluetoothGatt; | |
BluetoothGattCharacteristic characteristic; | |
boolean enabled; | |
... | |
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); | |
... | |
BluetoothGattDescriptor descriptor = characteristic.getDescriptor( | |
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); | |
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); | |
mBluetoothGatt.writeDescriptor(descriptor); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Override | |
// Characteristic notification | |
public void onCharacteristicChanged(BluetoothGatt gatt, | |
BluetoothGattCharacteristic characteristic) { | |
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void close() { | |
if (mBluetoothGatt == null) { | |
return; | |
} | |
mBluetoothGatt.close(); | |
mBluetoothGatt = null; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Use this check to determine whether BLE is supported on the device. Then | |
// you can selectively disable BLE-related features. | |
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { | |
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); | |
finish(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Initializes Bluetooth adapter. | |
final BluetoothManager bluetoothManager = | |
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); | |
mBluetoothAdapter = bluetoothManager.getAdapter(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private BluetoothAdapter mBluetoothAdapter; | |
... | |
// Ensures Bluetooth is available on the device and it is enabled. If not, | |
// displays a dialog requesting user permission to enable Bluetooth. | |
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { | |
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); | |
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Activity for scanning and displaying available BLE devices. | |
*/ | |
public class DeviceScanActivity extends ListActivity { | |
private BluetoothAdapter mBluetoothAdapter; | |
private boolean mScanning; | |
private Handler mHandler; | |
// Stops scanning after 10 seconds. | |
private static final long SCAN_PERIOD = 10000; | |
... | |
private void scanLeDevice(final boolean enable) { | |
if (enable) { | |
// Stops scanning after a pre-defined scan period. | |
mHandler.postDelayed(new Runnable() { | |
@Override | |
public void run() { | |
mScanning = false; | |
mBluetoothAdapter.stopLeScan(mLeScanCallback); | |
} | |
}, SCAN_PERIOD); | |
mScanning = true; | |
mBluetoothAdapter.startLeScan(mLeScanCallback); | |
} else { | |
mScanning = false; | |
mBluetoothAdapter.stopLeScan(mLeScanCallback); | |
} | |
... | |
} | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private LeDeviceListAdapter mLeDeviceListAdapter; | |
... | |
// Device scan callback. | |
private BluetoothAdapter.LeScanCallback mLeScanCallback = | |
new BluetoothAdapter.LeScanCallback() { | |
@Override | |
public void onLeScan(final BluetoothDevice device, int rssi, | |
byte[] scanRecord) { | |
runOnUiThread(new Runnable() { | |
@Override | |
public void run() { | |
mLeDeviceListAdapter.addDevice(device); | |
mLeDeviceListAdapter.notifyDataSetChanged(); | |
} | |
}); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mBluetoothGatt = device.connectGatt(this, false, mGattCallback); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A service that interacts with the BLE device via the Android BLE API. | |
public class BluetoothLeService extends Service { | |
private final static String TAG = BluetoothLeService.class.getSimpleName(); | |
private BluetoothManager mBluetoothManager; | |
private BluetoothAdapter mBluetoothAdapter; | |
private String mBluetoothDeviceAddress; | |
private BluetoothGatt mBluetoothGatt; | |
private int mConnectionState = STATE_DISCONNECTED; | |
private static final int STATE_DISCONNECTED = 0; | |
private static final int STATE_CONNECTING = 1; | |
private static final int STATE_CONNECTED = 2; | |
public final static String ACTION_GATT_CONNECTED = | |
"com.example.bluetooth.le.ACTION_GATT_CONNECTED"; | |
public final static String ACTION_GATT_DISCONNECTED = | |
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; | |
public final static String ACTION_GATT_SERVICES_DISCOVERED = | |
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED"; | |
public final static String ACTION_DATA_AVAILABLE = | |
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE"; | |
public final static String EXTRA_DATA = | |
"com.example.bluetooth.le.EXTRA_DATA"; | |
public final static UUID UUID_HEART_RATE_MEASUREMENT = | |
UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT); | |
// Various callback methods defined by the BLE API. | |
private final BluetoothGattCallback mGattCallback = | |
new BluetoothGattCallback() { | |
@Override | |
public void onConnectionStateChange(BluetoothGatt gatt, int status, | |
int newState) { | |
String intentAction; | |
if (newState == BluetoothProfile.STATE_CONNECTED) { | |
intentAction = ACTION_GATT_CONNECTED; | |
mConnectionState = STATE_CONNECTED; | |
broadcastUpdate(intentAction); | |
Log.i(TAG, "Connected to GATT server."); | |
Log.i(TAG, "Attempting to start service discovery:" + | |
mBluetoothGatt.discoverServices()); | |
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { | |
intentAction = ACTION_GATT_DISCONNECTED; | |
mConnectionState = STATE_DISCONNECTED; | |
Log.i(TAG, "Disconnected from GATT server."); | |
broadcastUpdate(intentAction); | |
} | |
} | |
@Override | |
// New services discovered | |
public void onServicesDiscovered(BluetoothGatt gatt, int status) { | |
if (status == BluetoothGatt.GATT_SUCCESS) { | |
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); | |
} else { | |
Log.w(TAG, "onServicesDiscovered received: " + status); | |
} | |
} | |
@Override | |
// Result of a characteristic read operation | |
public void onCharacteristicRead(BluetoothGatt gatt, | |
BluetoothGattCharacteristic characteristic, | |
int status) { | |
if (status == BluetoothGatt.GATT_SUCCESS) { | |
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); | |
} | |
} | |
... | |
}; | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private void broadcastUpdate(final String action) { | |
final Intent intent = new Intent(action); | |
sendBroadcast(intent); | |
} | |
private void broadcastUpdate(final String action, | |
final BluetoothGattCharacteristic characteristic) { | |
final Intent intent = new Intent(action); | |
// This is special handling for the Heart Rate Measurement profile. Data | |
// parsing is carried out as per profile specifications. | |
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { | |
int flag = characteristic.getProperties(); | |
int format = -1; | |
if ((flag & 0x01) != 0) { | |
format = BluetoothGattCharacteristic.FORMAT_UINT16; | |
Log.d(TAG, "Heart rate format UINT16."); | |
} else { | |
format = BluetoothGattCharacteristic.FORMAT_UINT8; | |
Log.d(TAG, "Heart rate format UINT8."); | |
} | |
final int heartRate = characteristic.getIntValue(format, 1); | |
Log.d(TAG, String.format("Received heart rate: %d", heartRate)); | |
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate)); | |
} else { | |
// For all other profiles, writes the data formatted in HEX. | |
final byte[] data = characteristic.getValue(); | |
if (data != null && data.length > 0) { | |
final StringBuilder stringBuilder = new StringBuilder(data.length); | |
for(byte byteChar : data) | |
stringBuilder.append(String.format("%02X ", byteChar)); | |
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + | |
stringBuilder.toString()); | |
} | |
} | |
sendBroadcast(intent); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment