diff --git a/sample_app/res/layout/activity_gatt_services.xml b/sample_app/res/layout/activity_gatt_services.xml
index 9fdc916..b60e56f 100644
--- a/sample_app/res/layout/activity_gatt_services.xml
+++ b/sample_app/res/layout/activity_gatt_services.xml
@@ -14,86 +14,112 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin" >
-
+ android:layout_alignParentTop="true"
+ android:columnCount="2"
+ android:useDefaultMargins="true" >
-
-
+ android:text="@string/label_device_address" />
-
-
-
+ style="@style/GridLayoutDataTextView" />
-
-
+ android:text="@string/label_state" />
-
+ style="@style/GridLayoutDataTextView" />
+
-
+
+
+ android:layout_alignParentBottom="true"
+ android:columnCount="2"
+ android:useDefaultMargins="true" >
-
-
+ android:text="@string/label_uuid" />
+
+
-
+ android:text="@string/label_desc" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:layout_height="fill_parent"
+ android:layout_above="@id/lowerSepparator"
+ android:layout_below="@id/upperSepparator" />
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/sample_app/res/layout/list_item_view_adrecord.xml b/sample_app/res/layout/list_item_view_adrecord.xml
index ed0adc6..e5cd158 100644
--- a/sample_app/res/layout/list_item_view_adrecord.xml
+++ b/sample_app/res/layout/list_item_view_adrecord.xml
@@ -23,7 +23,7 @@
style="@style/GridLayoutTitleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="As String:" />
+ android:text="@string/label_as_string" />
+ android:text="@string/label_as_array" />
Device Info
Invalid Device Data!
unknown
+ As String:
+ As Array:
+ Desc:
\ No newline at end of file
diff --git a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceControlActivity.java b/sample_app/src/uk/co/alt236/btlescan/activities/DeviceControlActivity.java
index d18d16b..a3ce5e6 100644
--- a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceControlActivity.java
+++ b/sample_app/src/uk/co/alt236/btlescan/activities/DeviceControlActivity.java
@@ -19,8 +19,10 @@ package uk.co.alt236.btlescan.activities;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import uk.co.alt236.bluetoothlelib.resolvers.GattAttributeResolver;
+import uk.co.alt236.bluetoothlelib.util.ByteUtils;
import uk.co.alt236.btlescan.R;
import uk.co.alt236.btlescan.services.BluetoothLeService;
import android.app.Activity;
@@ -41,6 +43,8 @@ import android.view.View;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
+import butterknife.ButterKnife;
+import butterknife.InjectView;
/**
* For a given BLE device, this Activity provides the user interface to connect, display data,
@@ -49,264 +53,286 @@ import android.widget.TextView;
* Bluetooth LE API.
*/
public class DeviceControlActivity extends Activity {
- private final static String TAG = DeviceControlActivity.class.getSimpleName();
+ private final static String TAG = DeviceControlActivity.class.getSimpleName();
- public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
- public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
+ public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
+ public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
- private TextView mConnectionState;
- private TextView mDataField;
- private String mDeviceName;
- private String mDeviceAddress;
- private ExpandableListView mGattServicesList;
- private BluetoothLeService mBluetoothLeService;
- private ArrayList> mGattCharacteristics =
- new ArrayList>();
- private boolean mConnected = false;
- private BluetoothGattCharacteristic mNotifyCharacteristic;
+ private static final String LIST_NAME = "NAME";
+ private static final String LIST_UUID = "UUID";
- private final String LIST_NAME = "NAME";
- private final String LIST_UUID = "UUID";
+ private BluetoothGattCharacteristic mNotifyCharacteristic;
+ private BluetoothLeService mBluetoothLeService;
+ private List> mGattCharacteristics = new ArrayList>();
+ private String mDeviceAddress;
+ private String mDeviceName;
- // Code to manage Service lifecycle.
- private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @InjectView(R.id.gatt_services_list) ExpandableListView mGattServicesList;
+ @InjectView(R.id.connection_state) TextView mConnectionState;
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder service) {
- mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
- if (!mBluetoothLeService.initialize()) {
- Log.e(TAG, "Unable to initialize Bluetooth");
- finish();
- }
- // Automatically connects to the device upon successful start-up initialization.
- mBluetoothLeService.connect(mDeviceAddress);
- }
+ @InjectView(R.id.uuid) TextView mGattUUID;
+ @InjectView(R.id.description) TextView mGattUUIDDesc;
+ @InjectView(R.id.data_as_string) TextView mDataAsString;
+ @InjectView(R.id.data_as_array) TextView mDataAsArray;
- @Override
- public void onServiceDisconnected(ComponentName componentName) {
- mBluetoothLeService = null;
- }
- };
+ private boolean mConnected = false;
- // 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));
- }
- }
- };
+ // Code to manage Service lifecycle.
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName componentName, IBinder service) {
+ mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
+ if (!mBluetoothLeService.initialize()) {
+ Log.e(TAG, "Unable to initialize Bluetooth");
+ finish();
+ }
+ // Automatically connects to the device upon successful start-up initialization.
+ mBluetoothLeService.connect(mDeviceAddress);
+ }
- // If a given GATT characteristic is selected, check for supported features. This sample
- // demonstrates 'Read' and 'Notify' features. See
- // http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
- // list of supported characteristic features.
- private final ExpandableListView.OnChildClickListener servicesListClickListner =
- new ExpandableListView.OnChildClickListener() {
- @Override
- public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
- int childPosition, long id) {
- if (mGattCharacteristics != null) {
- final BluetoothGattCharacteristic characteristic =
- mGattCharacteristics.get(groupPosition).get(childPosition);
- final int charaProp = characteristic.getProperties();
- if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
- // If there is an active notification on a characteristic, clear
- // it first so it doesn't update the data field on the user interface.
- if (mNotifyCharacteristic != null) {
- mBluetoothLeService.setCharacteristicNotification(
- mNotifyCharacteristic, false);
- mNotifyCharacteristic = null;
- }
- mBluetoothLeService.readCharacteristic(characteristic);
- }
- if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
- mNotifyCharacteristic = characteristic;
- mBluetoothLeService.setCharacteristicNotification(
- characteristic, true);
- }
- return true;
- }
- return false;
- }
- };
+ @Override
+ public void onServiceDisconnected(ComponentName componentName) {
+ mBluetoothLeService = null;
+ }
+ };
- private void clearUI() {
- mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
- mDataField.setText(R.string.no_data);
- }
+ // 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)) {
+ final String noData = getString(R.string.no_data);
+ final String uuid = intent.getStringExtra(BluetoothLeService.EXTRA_UUID_CHAR);
+ final byte[] dataArr = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA_RAW);
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_gatt_services);
+ mGattUUID.setText(tryString(uuid, noData));
+ mGattUUIDDesc.setText(GattAttributeResolver.getAttributeName(uuid, getString(R.string.unknown)));
+ mDataAsArray.setText(ByteUtils.byteArrayToHexString(dataArr));
+ mDataAsString.setText(new String(dataArr));
+ }
+ }
+ };
- final Intent intent = getIntent();
- mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
- mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
+ // If a given GATT characteristic is selected, check for supported features. This sample
+ // demonstrates 'Read' and 'Notify' features. See
+ // http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
+ // list of supported characteristic features.
+ private final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() {
+ @Override
+ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+ if (mGattCharacteristics != null) {
+ final BluetoothGattCharacteristic characteristic = mGattCharacteristics.get(groupPosition).get(childPosition);
+ final int charaProp = characteristic.getProperties();
+ if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
+ // If there is an active notification on a characteristic, clear
+ // it first so it doesn't update the data field on the user interface.
+ if (mNotifyCharacteristic != null) {
+ mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
+ mNotifyCharacteristic = null;
+ }
+ mBluetoothLeService.readCharacteristic(characteristic);
+ }
+ if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
+ mNotifyCharacteristic = characteristic;
+ mBluetoothLeService.setCharacteristicNotification(characteristic, true);
+ }
+ return true;
+ }
+ return false;
+ }
+ };
- // Sets up UI references.
- ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
- mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);
- mGattServicesList.setOnChildClickListener(servicesListClickListner);
- mConnectionState = (TextView) findViewById(R.id.connection_state);
- mDataField = (TextView) findViewById(R.id.data_value);
- getActionBar().setTitle(mDeviceName);
- getActionBar().setDisplayHomeAsUpEnabled(true);
- Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
- bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
- }
+ private void clearUI() {
+ mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
+ mGattUUID.setText(R.string.no_data);
+ mGattUUIDDesc.setText(R.string.no_data);
+ mDataAsArray.setText(R.string.no_data);
+ mDataAsString.setText(R.string.no_data);
- @Override
- protected void onResume() {
- super.onResume();
- registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
- if (mBluetoothLeService != null) {
- final boolean result = mBluetoothLeService.connect(mDeviceAddress);
- Log.d(TAG, "Connect request result=" + result);
- }
- }
+ }
- @Override
- protected void onPause() {
- super.onPause();
- unregisterReceiver(mGattUpdateReceiver);
- }
+ // 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 gattServices) {
+ if (gattServices == null) return;
+ String uuid = null;
+ final String unknownServiceString = getResources().getString(R.string.unknown_service);
+ final String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
+ final List