1*90c8c64dSAndroid Build Coastguard Worker /* 2*90c8c64dSAndroid Build Coastguard Worker * Copyright (C) 2013 The Android Open Source Project 3*90c8c64dSAndroid Build Coastguard Worker * 4*90c8c64dSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*90c8c64dSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*90c8c64dSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*90c8c64dSAndroid Build Coastguard Worker * 8*90c8c64dSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*90c8c64dSAndroid Build Coastguard Worker * 10*90c8c64dSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*90c8c64dSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*90c8c64dSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*90c8c64dSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*90c8c64dSAndroid Build Coastguard Worker * limitations under the License. 15*90c8c64dSAndroid Build Coastguard Worker */ 16*90c8c64dSAndroid Build Coastguard Worker 17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.bluetoothlegatt; 18*90c8c64dSAndroid Build Coastguard Worker 19*90c8c64dSAndroid Build Coastguard Worker import android.app.Activity; 20*90c8c64dSAndroid Build Coastguard Worker import android.bluetooth.BluetoothGattCharacteristic; 21*90c8c64dSAndroid Build Coastguard Worker import android.bluetooth.BluetoothGattService; 22*90c8c64dSAndroid Build Coastguard Worker import android.content.BroadcastReceiver; 23*90c8c64dSAndroid Build Coastguard Worker import android.content.ComponentName; 24*90c8c64dSAndroid Build Coastguard Worker import android.content.Context; 25*90c8c64dSAndroid Build Coastguard Worker import android.content.Intent; 26*90c8c64dSAndroid Build Coastguard Worker import android.content.IntentFilter; 27*90c8c64dSAndroid Build Coastguard Worker import android.content.ServiceConnection; 28*90c8c64dSAndroid Build Coastguard Worker import android.os.Bundle; 29*90c8c64dSAndroid Build Coastguard Worker import android.os.IBinder; 30*90c8c64dSAndroid Build Coastguard Worker import android.util.Log; 31*90c8c64dSAndroid Build Coastguard Worker import android.view.Menu; 32*90c8c64dSAndroid Build Coastguard Worker import android.view.MenuItem; 33*90c8c64dSAndroid Build Coastguard Worker import android.view.View; 34*90c8c64dSAndroid Build Coastguard Worker import android.widget.ExpandableListView; 35*90c8c64dSAndroid Build Coastguard Worker import android.widget.SimpleExpandableListAdapter; 36*90c8c64dSAndroid Build Coastguard Worker import android.widget.TextView; 37*90c8c64dSAndroid Build Coastguard Worker 38*90c8c64dSAndroid Build Coastguard Worker import java.util.ArrayList; 39*90c8c64dSAndroid Build Coastguard Worker import java.util.HashMap; 40*90c8c64dSAndroid Build Coastguard Worker import java.util.List; 41*90c8c64dSAndroid Build Coastguard Worker 42*90c8c64dSAndroid Build Coastguard Worker /** 43*90c8c64dSAndroid Build Coastguard Worker * For a given BLE device, this Activity provides the user interface to connect, display data, 44*90c8c64dSAndroid Build Coastguard Worker * and display GATT services and characteristics supported by the device. The Activity 45*90c8c64dSAndroid Build Coastguard Worker * communicates with {@code BluetoothLeService}, which in turn interacts with the 46*90c8c64dSAndroid Build Coastguard Worker * Bluetooth LE API. 47*90c8c64dSAndroid Build Coastguard Worker */ 48*90c8c64dSAndroid Build Coastguard Worker public class DeviceControlActivity extends Activity { 49*90c8c64dSAndroid Build Coastguard Worker private final static String TAG = DeviceControlActivity.class.getSimpleName(); 50*90c8c64dSAndroid Build Coastguard Worker 51*90c8c64dSAndroid Build Coastguard Worker public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME"; 52*90c8c64dSAndroid Build Coastguard Worker public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS"; 53*90c8c64dSAndroid Build Coastguard Worker 54*90c8c64dSAndroid Build Coastguard Worker private TextView mConnectionState; 55*90c8c64dSAndroid Build Coastguard Worker private TextView mDataField; 56*90c8c64dSAndroid Build Coastguard Worker private String mDeviceName; 57*90c8c64dSAndroid Build Coastguard Worker private String mDeviceAddress; 58*90c8c64dSAndroid Build Coastguard Worker private ExpandableListView mGattServicesList; 59*90c8c64dSAndroid Build Coastguard Worker private BluetoothLeService mBluetoothLeService; 60*90c8c64dSAndroid Build Coastguard Worker private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = 61*90c8c64dSAndroid Build Coastguard Worker new ArrayList<ArrayList<BluetoothGattCharacteristic>>(); 62*90c8c64dSAndroid Build Coastguard Worker private boolean mConnected = false; 63*90c8c64dSAndroid Build Coastguard Worker private BluetoothGattCharacteristic mNotifyCharacteristic; 64*90c8c64dSAndroid Build Coastguard Worker 65*90c8c64dSAndroid Build Coastguard Worker private final String LIST_NAME = "NAME"; 66*90c8c64dSAndroid Build Coastguard Worker private final String LIST_UUID = "UUID"; 67*90c8c64dSAndroid Build Coastguard Worker 68*90c8c64dSAndroid Build Coastguard Worker // Code to manage Service lifecycle. 69*90c8c64dSAndroid Build Coastguard Worker private final ServiceConnection mServiceConnection = new ServiceConnection() { 70*90c8c64dSAndroid Build Coastguard Worker 71*90c8c64dSAndroid Build Coastguard Worker @Override 72*90c8c64dSAndroid Build Coastguard Worker public void onServiceConnected(ComponentName componentName, IBinder service) { 73*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); 74*90c8c64dSAndroid Build Coastguard Worker if (!mBluetoothLeService.initialize()) { 75*90c8c64dSAndroid Build Coastguard Worker Log.e(TAG, "Unable to initialize Bluetooth"); 76*90c8c64dSAndroid Build Coastguard Worker finish(); 77*90c8c64dSAndroid Build Coastguard Worker } 78*90c8c64dSAndroid Build Coastguard Worker // Automatically connects to the device upon successful start-up initialization. 79*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService.connect(mDeviceAddress); 80*90c8c64dSAndroid Build Coastguard Worker } 81*90c8c64dSAndroid Build Coastguard Worker 82*90c8c64dSAndroid Build Coastguard Worker @Override 83*90c8c64dSAndroid Build Coastguard Worker public void onServiceDisconnected(ComponentName componentName) { 84*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService = null; 85*90c8c64dSAndroid Build Coastguard Worker } 86*90c8c64dSAndroid Build Coastguard Worker }; 87*90c8c64dSAndroid Build Coastguard Worker 88*90c8c64dSAndroid Build Coastguard Worker // Handles various events fired by the Service. 89*90c8c64dSAndroid Build Coastguard Worker // ACTION_GATT_CONNECTED: connected to a GATT server. 90*90c8c64dSAndroid Build Coastguard Worker // ACTION_GATT_DISCONNECTED: disconnected from a GATT server. 91*90c8c64dSAndroid Build Coastguard Worker // ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services. 92*90c8c64dSAndroid Build Coastguard Worker // ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read 93*90c8c64dSAndroid Build Coastguard Worker // or notification operations. 94*90c8c64dSAndroid Build Coastguard Worker private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { 95*90c8c64dSAndroid Build Coastguard Worker @Override 96*90c8c64dSAndroid Build Coastguard Worker public void onReceive(Context context, Intent intent) { 97*90c8c64dSAndroid Build Coastguard Worker final String action = intent.getAction(); 98*90c8c64dSAndroid Build Coastguard Worker if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { 99*90c8c64dSAndroid Build Coastguard Worker mConnected = true; 100*90c8c64dSAndroid Build Coastguard Worker updateConnectionState(R.string.connected); 101*90c8c64dSAndroid Build Coastguard Worker invalidateOptionsMenu(); 102*90c8c64dSAndroid Build Coastguard Worker } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { 103*90c8c64dSAndroid Build Coastguard Worker mConnected = false; 104*90c8c64dSAndroid Build Coastguard Worker updateConnectionState(R.string.disconnected); 105*90c8c64dSAndroid Build Coastguard Worker invalidateOptionsMenu(); 106*90c8c64dSAndroid Build Coastguard Worker clearUI(); 107*90c8c64dSAndroid Build Coastguard Worker } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { 108*90c8c64dSAndroid Build Coastguard Worker // Show all the supported services and characteristics on the user interface. 109*90c8c64dSAndroid Build Coastguard Worker displayGattServices(mBluetoothLeService.getSupportedGattServices()); 110*90c8c64dSAndroid Build Coastguard Worker } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { 111*90c8c64dSAndroid Build Coastguard Worker displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); 112*90c8c64dSAndroid Build Coastguard Worker } 113*90c8c64dSAndroid Build Coastguard Worker } 114*90c8c64dSAndroid Build Coastguard Worker }; 115*90c8c64dSAndroid Build Coastguard Worker 116*90c8c64dSAndroid Build Coastguard Worker // If a given GATT characteristic is selected, check for supported features. This sample 117*90c8c64dSAndroid Build Coastguard Worker // demonstrates 'Read' and 'Notify' features. See 118*90c8c64dSAndroid Build Coastguard Worker // http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete 119*90c8c64dSAndroid Build Coastguard Worker // list of supported characteristic features. 120*90c8c64dSAndroid Build Coastguard Worker private final ExpandableListView.OnChildClickListener servicesListClickListner = 121*90c8c64dSAndroid Build Coastguard Worker new ExpandableListView.OnChildClickListener() { 122*90c8c64dSAndroid Build Coastguard Worker @Override 123*90c8c64dSAndroid Build Coastguard Worker public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, 124*90c8c64dSAndroid Build Coastguard Worker int childPosition, long id) { 125*90c8c64dSAndroid Build Coastguard Worker if (mGattCharacteristics != null) { 126*90c8c64dSAndroid Build Coastguard Worker final BluetoothGattCharacteristic characteristic = 127*90c8c64dSAndroid Build Coastguard Worker mGattCharacteristics.get(groupPosition).get(childPosition); 128*90c8c64dSAndroid Build Coastguard Worker final int charaProp = characteristic.getProperties(); 129*90c8c64dSAndroid Build Coastguard Worker if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) { 130*90c8c64dSAndroid Build Coastguard Worker // If there is an active notification on a characteristic, clear 131*90c8c64dSAndroid Build Coastguard Worker // it first so it doesn't update the data field on the user interface. 132*90c8c64dSAndroid Build Coastguard Worker if (mNotifyCharacteristic != null) { 133*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService.setCharacteristicNotification( 134*90c8c64dSAndroid Build Coastguard Worker mNotifyCharacteristic, false); 135*90c8c64dSAndroid Build Coastguard Worker mNotifyCharacteristic = null; 136*90c8c64dSAndroid Build Coastguard Worker } 137*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService.readCharacteristic(characteristic); 138*90c8c64dSAndroid Build Coastguard Worker } 139*90c8c64dSAndroid Build Coastguard Worker if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { 140*90c8c64dSAndroid Build Coastguard Worker mNotifyCharacteristic = characteristic; 141*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService.setCharacteristicNotification( 142*90c8c64dSAndroid Build Coastguard Worker characteristic, true); 143*90c8c64dSAndroid Build Coastguard Worker } 144*90c8c64dSAndroid Build Coastguard Worker return true; 145*90c8c64dSAndroid Build Coastguard Worker } 146*90c8c64dSAndroid Build Coastguard Worker return false; 147*90c8c64dSAndroid Build Coastguard Worker } 148*90c8c64dSAndroid Build Coastguard Worker }; 149*90c8c64dSAndroid Build Coastguard Worker clearUI()150*90c8c64dSAndroid Build Coastguard Worker private void clearUI() { 151*90c8c64dSAndroid Build Coastguard Worker mGattServicesList.setAdapter((SimpleExpandableListAdapter) null); 152*90c8c64dSAndroid Build Coastguard Worker mDataField.setText(R.string.no_data); 153*90c8c64dSAndroid Build Coastguard Worker } 154*90c8c64dSAndroid Build Coastguard Worker 155*90c8c64dSAndroid Build Coastguard Worker @Override onCreate(Bundle savedInstanceState)156*90c8c64dSAndroid Build Coastguard Worker public void onCreate(Bundle savedInstanceState) { 157*90c8c64dSAndroid Build Coastguard Worker super.onCreate(savedInstanceState); 158*90c8c64dSAndroid Build Coastguard Worker setContentView(R.layout.gatt_services_characteristics); 159*90c8c64dSAndroid Build Coastguard Worker 160*90c8c64dSAndroid Build Coastguard Worker final Intent intent = getIntent(); 161*90c8c64dSAndroid Build Coastguard Worker mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME); 162*90c8c64dSAndroid Build Coastguard Worker mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS); 163*90c8c64dSAndroid Build Coastguard Worker 164*90c8c64dSAndroid Build Coastguard Worker // Sets up UI references. 165*90c8c64dSAndroid Build Coastguard Worker ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress); 166*90c8c64dSAndroid Build Coastguard Worker mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list); 167*90c8c64dSAndroid Build Coastguard Worker mGattServicesList.setOnChildClickListener(servicesListClickListner); 168*90c8c64dSAndroid Build Coastguard Worker mConnectionState = (TextView) findViewById(R.id.connection_state); 169*90c8c64dSAndroid Build Coastguard Worker mDataField = (TextView) findViewById(R.id.data_value); 170*90c8c64dSAndroid Build Coastguard Worker 171*90c8c64dSAndroid Build Coastguard Worker getActionBar().setTitle(mDeviceName); 172*90c8c64dSAndroid Build Coastguard Worker getActionBar().setDisplayHomeAsUpEnabled(true); 173*90c8c64dSAndroid Build Coastguard Worker Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); 174*90c8c64dSAndroid Build Coastguard Worker bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); 175*90c8c64dSAndroid Build Coastguard Worker } 176*90c8c64dSAndroid Build Coastguard Worker 177*90c8c64dSAndroid Build Coastguard Worker @Override onResume()178*90c8c64dSAndroid Build Coastguard Worker protected void onResume() { 179*90c8c64dSAndroid Build Coastguard Worker super.onResume(); 180*90c8c64dSAndroid Build Coastguard Worker registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); 181*90c8c64dSAndroid Build Coastguard Worker if (mBluetoothLeService != null) { 182*90c8c64dSAndroid Build Coastguard Worker final boolean result = mBluetoothLeService.connect(mDeviceAddress); 183*90c8c64dSAndroid Build Coastguard Worker Log.d(TAG, "Connect request result=" + result); 184*90c8c64dSAndroid Build Coastguard Worker } 185*90c8c64dSAndroid Build Coastguard Worker } 186*90c8c64dSAndroid Build Coastguard Worker 187*90c8c64dSAndroid Build Coastguard Worker @Override onPause()188*90c8c64dSAndroid Build Coastguard Worker protected void onPause() { 189*90c8c64dSAndroid Build Coastguard Worker super.onPause(); 190*90c8c64dSAndroid Build Coastguard Worker unregisterReceiver(mGattUpdateReceiver); 191*90c8c64dSAndroid Build Coastguard Worker } 192*90c8c64dSAndroid Build Coastguard Worker 193*90c8c64dSAndroid Build Coastguard Worker @Override onDestroy()194*90c8c64dSAndroid Build Coastguard Worker protected void onDestroy() { 195*90c8c64dSAndroid Build Coastguard Worker super.onDestroy(); 196*90c8c64dSAndroid Build Coastguard Worker unbindService(mServiceConnection); 197*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService = null; 198*90c8c64dSAndroid Build Coastguard Worker } 199*90c8c64dSAndroid Build Coastguard Worker 200*90c8c64dSAndroid Build Coastguard Worker @Override onCreateOptionsMenu(Menu menu)201*90c8c64dSAndroid Build Coastguard Worker public boolean onCreateOptionsMenu(Menu menu) { 202*90c8c64dSAndroid Build Coastguard Worker getMenuInflater().inflate(R.menu.gatt_services, menu); 203*90c8c64dSAndroid Build Coastguard Worker if (mConnected) { 204*90c8c64dSAndroid Build Coastguard Worker menu.findItem(R.id.menu_connect).setVisible(false); 205*90c8c64dSAndroid Build Coastguard Worker menu.findItem(R.id.menu_disconnect).setVisible(true); 206*90c8c64dSAndroid Build Coastguard Worker } else { 207*90c8c64dSAndroid Build Coastguard Worker menu.findItem(R.id.menu_connect).setVisible(true); 208*90c8c64dSAndroid Build Coastguard Worker menu.findItem(R.id.menu_disconnect).setVisible(false); 209*90c8c64dSAndroid Build Coastguard Worker } 210*90c8c64dSAndroid Build Coastguard Worker return true; 211*90c8c64dSAndroid Build Coastguard Worker } 212*90c8c64dSAndroid Build Coastguard Worker 213*90c8c64dSAndroid Build Coastguard Worker @Override onOptionsItemSelected(MenuItem item)214*90c8c64dSAndroid Build Coastguard Worker public boolean onOptionsItemSelected(MenuItem item) { 215*90c8c64dSAndroid Build Coastguard Worker switch(item.getItemId()) { 216*90c8c64dSAndroid Build Coastguard Worker case R.id.menu_connect: 217*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService.connect(mDeviceAddress); 218*90c8c64dSAndroid Build Coastguard Worker return true; 219*90c8c64dSAndroid Build Coastguard Worker case R.id.menu_disconnect: 220*90c8c64dSAndroid Build Coastguard Worker mBluetoothLeService.disconnect(); 221*90c8c64dSAndroid Build Coastguard Worker return true; 222*90c8c64dSAndroid Build Coastguard Worker case android.R.id.home: 223*90c8c64dSAndroid Build Coastguard Worker onBackPressed(); 224*90c8c64dSAndroid Build Coastguard Worker return true; 225*90c8c64dSAndroid Build Coastguard Worker } 226*90c8c64dSAndroid Build Coastguard Worker return super.onOptionsItemSelected(item); 227*90c8c64dSAndroid Build Coastguard Worker } 228*90c8c64dSAndroid Build Coastguard Worker updateConnectionState(final int resourceId)229*90c8c64dSAndroid Build Coastguard Worker private void updateConnectionState(final int resourceId) { 230*90c8c64dSAndroid Build Coastguard Worker runOnUiThread(new Runnable() { 231*90c8c64dSAndroid Build Coastguard Worker @Override 232*90c8c64dSAndroid Build Coastguard Worker public void run() { 233*90c8c64dSAndroid Build Coastguard Worker mConnectionState.setText(resourceId); 234*90c8c64dSAndroid Build Coastguard Worker } 235*90c8c64dSAndroid Build Coastguard Worker }); 236*90c8c64dSAndroid Build Coastguard Worker } 237*90c8c64dSAndroid Build Coastguard Worker displayData(String data)238*90c8c64dSAndroid Build Coastguard Worker private void displayData(String data) { 239*90c8c64dSAndroid Build Coastguard Worker if (data != null) { 240*90c8c64dSAndroid Build Coastguard Worker mDataField.setText(data); 241*90c8c64dSAndroid Build Coastguard Worker } 242*90c8c64dSAndroid Build Coastguard Worker } 243*90c8c64dSAndroid Build Coastguard Worker 244*90c8c64dSAndroid Build Coastguard Worker // Demonstrates how to iterate through the supported GATT Services/Characteristics. 245*90c8c64dSAndroid Build Coastguard Worker // In this sample, we populate the data structure that is bound to the ExpandableListView 246*90c8c64dSAndroid Build Coastguard Worker // on the UI. displayGattServices(List<BluetoothGattService> gattServices)247*90c8c64dSAndroid Build Coastguard Worker private void displayGattServices(List<BluetoothGattService> gattServices) { 248*90c8c64dSAndroid Build Coastguard Worker if (gattServices == null) return; 249*90c8c64dSAndroid Build Coastguard Worker String uuid = null; 250*90c8c64dSAndroid Build Coastguard Worker String unknownServiceString = getResources().getString(R.string.unknown_service); 251*90c8c64dSAndroid Build Coastguard Worker String unknownCharaString = getResources().getString(R.string.unknown_characteristic); 252*90c8c64dSAndroid Build Coastguard Worker ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>(); 253*90c8c64dSAndroid Build Coastguard Worker ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData 254*90c8c64dSAndroid Build Coastguard Worker = new ArrayList<ArrayList<HashMap<String, String>>>(); 255*90c8c64dSAndroid Build Coastguard Worker mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>(); 256*90c8c64dSAndroid Build Coastguard Worker 257*90c8c64dSAndroid Build Coastguard Worker // Loops through available GATT Services. 258*90c8c64dSAndroid Build Coastguard Worker for (BluetoothGattService gattService : gattServices) { 259*90c8c64dSAndroid Build Coastguard Worker HashMap<String, String> currentServiceData = new HashMap<String, String>(); 260*90c8c64dSAndroid Build Coastguard Worker uuid = gattService.getUuid().toString(); 261*90c8c64dSAndroid Build Coastguard Worker currentServiceData.put( 262*90c8c64dSAndroid Build Coastguard Worker LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString)); 263*90c8c64dSAndroid Build Coastguard Worker currentServiceData.put(LIST_UUID, uuid); 264*90c8c64dSAndroid Build Coastguard Worker gattServiceData.add(currentServiceData); 265*90c8c64dSAndroid Build Coastguard Worker 266*90c8c64dSAndroid Build Coastguard Worker ArrayList<HashMap<String, String>> gattCharacteristicGroupData = 267*90c8c64dSAndroid Build Coastguard Worker new ArrayList<HashMap<String, String>>(); 268*90c8c64dSAndroid Build Coastguard Worker List<BluetoothGattCharacteristic> gattCharacteristics = 269*90c8c64dSAndroid Build Coastguard Worker gattService.getCharacteristics(); 270*90c8c64dSAndroid Build Coastguard Worker ArrayList<BluetoothGattCharacteristic> charas = 271*90c8c64dSAndroid Build Coastguard Worker new ArrayList<BluetoothGattCharacteristic>(); 272*90c8c64dSAndroid Build Coastguard Worker 273*90c8c64dSAndroid Build Coastguard Worker // Loops through available Characteristics. 274*90c8c64dSAndroid Build Coastguard Worker for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { 275*90c8c64dSAndroid Build Coastguard Worker charas.add(gattCharacteristic); 276*90c8c64dSAndroid Build Coastguard Worker HashMap<String, String> currentCharaData = new HashMap<String, String>(); 277*90c8c64dSAndroid Build Coastguard Worker uuid = gattCharacteristic.getUuid().toString(); 278*90c8c64dSAndroid Build Coastguard Worker currentCharaData.put( 279*90c8c64dSAndroid Build Coastguard Worker LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString)); 280*90c8c64dSAndroid Build Coastguard Worker currentCharaData.put(LIST_UUID, uuid); 281*90c8c64dSAndroid Build Coastguard Worker gattCharacteristicGroupData.add(currentCharaData); 282*90c8c64dSAndroid Build Coastguard Worker } 283*90c8c64dSAndroid Build Coastguard Worker mGattCharacteristics.add(charas); 284*90c8c64dSAndroid Build Coastguard Worker gattCharacteristicData.add(gattCharacteristicGroupData); 285*90c8c64dSAndroid Build Coastguard Worker } 286*90c8c64dSAndroid Build Coastguard Worker 287*90c8c64dSAndroid Build Coastguard Worker SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter( 288*90c8c64dSAndroid Build Coastguard Worker this, 289*90c8c64dSAndroid Build Coastguard Worker gattServiceData, 290*90c8c64dSAndroid Build Coastguard Worker android.R.layout.simple_expandable_list_item_2, 291*90c8c64dSAndroid Build Coastguard Worker new String[] {LIST_NAME, LIST_UUID}, 292*90c8c64dSAndroid Build Coastguard Worker new int[] { android.R.id.text1, android.R.id.text2 }, 293*90c8c64dSAndroid Build Coastguard Worker gattCharacteristicData, 294*90c8c64dSAndroid Build Coastguard Worker android.R.layout.simple_expandable_list_item_2, 295*90c8c64dSAndroid Build Coastguard Worker new String[] {LIST_NAME, LIST_UUID}, 296*90c8c64dSAndroid Build Coastguard Worker new int[] { android.R.id.text1, android.R.id.text2 } 297*90c8c64dSAndroid Build Coastguard Worker ); 298*90c8c64dSAndroid Build Coastguard Worker mGattServicesList.setAdapter(gattServiceAdapter); 299*90c8c64dSAndroid Build Coastguard Worker } 300*90c8c64dSAndroid Build Coastguard Worker makeGattUpdateIntentFilter()301*90c8c64dSAndroid Build Coastguard Worker private static IntentFilter makeGattUpdateIntentFilter() { 302*90c8c64dSAndroid Build Coastguard Worker final IntentFilter intentFilter = new IntentFilter(); 303*90c8c64dSAndroid Build Coastguard Worker intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED); 304*90c8c64dSAndroid Build Coastguard Worker intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED); 305*90c8c64dSAndroid Build Coastguard Worker intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED); 306*90c8c64dSAndroid Build Coastguard Worker intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE); 307*90c8c64dSAndroid Build Coastguard Worker return intentFilter; 308*90c8c64dSAndroid Build Coastguard Worker } 309*90c8c64dSAndroid Build Coastguard Worker } 310