Please note that the contents of this offline web site may be out of date. To access the most recent documentation visit the online version .
Note that links that point to online resources are green in color and will open in a new window.
We would love it if you could give us feedback about this material by filling this form (You have to be online to fill it)
BluetoothLeGatt / src / com.example.android.bluetoothlegatt /

DeviceControlActivity.java

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