Skip to content

Most visited

Recently visited

navigation
BluetoothLeGatt / src / com.example.android.bluetoothlegatt /

DeviceScanActivity.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.app.ListActivity;
21
import android.bluetooth.BluetoothAdapter;
22
import android.bluetooth.BluetoothDevice;
23
import android.bluetooth.BluetoothManager;
24
import android.content.Context;
25
import android.content.Intent;
26
import android.content.pm.PackageManager;
27
import android.os.Bundle;
28
import android.os.Handler;
29
import android.view.LayoutInflater;
30
import android.view.Menu;
31
import android.view.MenuItem;
32
import android.view.View;
33
import android.view.ViewGroup;
34
import android.widget.BaseAdapter;
35
import android.widget.ListView;
36
import android.widget.TextView;
37
import android.widget.Toast;
38
 
39
import java.util.ArrayList;
40
 
41
/**
42
 * Activity for scanning and displaying available Bluetooth LE devices.
43
 */
44
public class DeviceScanActivity extends ListActivity {
45
    private LeDeviceListAdapter mLeDeviceListAdapter;
46
    private BluetoothAdapter mBluetoothAdapter;
47
    private boolean mScanning;
48
    private Handler mHandler;
49
 
50
    private static final int REQUEST_ENABLE_BT = 1;
51
    // Stops scanning after 10 seconds.
52
    private static final long SCAN_PERIOD = 10000;
53
 
54
    @Override
55
    public void onCreate(Bundle savedInstanceState) {
56
        super.onCreate(savedInstanceState);
57
        getActionBar().setTitle(R.string.title_devices);
58
        mHandler = new Handler();
59
 
60
        // Use this check to determine whether BLE is supported on the device.  Then you can
61
        // selectively disable BLE-related features.
62
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
63
            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
64
            finish();
65
        }
66
 
67
        // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
68
        // BluetoothAdapter through BluetoothManager.
69
        final BluetoothManager bluetoothManager =
70
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
71
        mBluetoothAdapter = bluetoothManager.getAdapter();
72
 
73
        // Checks if Bluetooth is supported on the device.
74
        if (mBluetoothAdapter == null) {
75
            Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
76
            finish();
77
            return;
78
        }
79
    }
80
 
81
    @Override
82
    public boolean onCreateOptionsMenu(Menu menu) {
83
        getMenuInflater().inflate(R.menu.main, menu);
84
        if (!mScanning) {
85
            menu.findItem(R.id.menu_stop).setVisible(false);
86
            menu.findItem(R.id.menu_scan).setVisible(true);
87
            menu.findItem(R.id.menu_refresh).setActionView(null);
88
        } else {
89
            menu.findItem(R.id.menu_stop).setVisible(true);
90
            menu.findItem(R.id.menu_scan).setVisible(false);
91
            menu.findItem(R.id.menu_refresh).setActionView(
92
                    R.layout.actionbar_indeterminate_progress);
93
        }
94
        return true;
95
    }
96
 
97
    @Override
98
    public boolean onOptionsItemSelected(MenuItem item) {
99
        switch (item.getItemId()) {
100
            case R.id.menu_scan:
101
                mLeDeviceListAdapter.clear();
102
                scanLeDevice(true);
103
                break;
104
            case R.id.menu_stop:
105
                scanLeDevice(false);
106
                break;
107
        }
108
        return true;
109
    }
110
 
111
    @Override
112
    protected void onResume() {
113
        super.onResume();
114
 
115
        // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
116
        // fire an intent to display a dialog asking the user to grant permission to enable it.
117
        if (!mBluetoothAdapter.isEnabled()) {
118
            if (!mBluetoothAdapter.isEnabled()) {
119
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
120
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
121
            }
122
        }
123
 
124
        // Initializes list view adapter.
125
        mLeDeviceListAdapter = new LeDeviceListAdapter();
126
        setListAdapter(mLeDeviceListAdapter);
127
        scanLeDevice(true);
128
    }
129
 
130
    @Override
131
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
132
        // User chose not to enable Bluetooth.
133
        if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
134
            finish();
135
            return;
136
        }
137
        super.onActivityResult(requestCode, resultCode, data);
138
    }
139
 
140
    @Override
141
    protected void onPause() {
142
        super.onPause();
143
        scanLeDevice(false);
144
        mLeDeviceListAdapter.clear();
145
    }
146
 
147
    @Override
148
    protected void onListItemClick(ListView l, View v, int position, long id) {
149
        final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
150
        if (device == null) return;
151
        final Intent intent = new Intent(this, DeviceControlActivity.class);
152
        intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
153
        intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
154
        if (mScanning) {
155
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
156
            mScanning = false;
157
        }
158
        startActivity(intent);
159
    }
160
 
161
    private void scanLeDevice(final boolean enable) {
162
        if (enable) {
163
            // Stops scanning after a pre-defined scan period.
164
            mHandler.postDelayed(new Runnable() {
165
                @Override
166
                public void run() {
167
                    mScanning = false;
168
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
169
                    invalidateOptionsMenu();
170
                }
171
            }, SCAN_PERIOD);
172
 
173
            mScanning = true;
174
            mBluetoothAdapter.startLeScan(mLeScanCallback);
175
        } else {
176
            mScanning = false;
177
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
178
        }
179
        invalidateOptionsMenu();
180
    }
181
 
182
    // Adapter for holding devices found through scanning.
183
    private class LeDeviceListAdapter extends BaseAdapter {
184
        private ArrayList<BluetoothDevice> mLeDevices;
185
        private LayoutInflater mInflator;
186
 
187
        public LeDeviceListAdapter() {
188
            super();
189
            mLeDevices = new ArrayList<BluetoothDevice>();
190
            mInflator = DeviceScanActivity.this.getLayoutInflater();
191
        }
192
 
193
        public void addDevice(BluetoothDevice device) {
194
            if(!mLeDevices.contains(device)) {
195
                mLeDevices.add(device);
196
            }
197
        }
198
 
199
        public BluetoothDevice getDevice(int position) {
200
            return mLeDevices.get(position);
201
        }
202
 
203
        public void clear() {
204
            mLeDevices.clear();
205
        }
206
 
207
        @Override
208
        public int getCount() {
209
            return mLeDevices.size();
210
        }
211
 
212
        @Override
213
        public Object getItem(int i) {
214
            return mLeDevices.get(i);
215
        }
216
 
217
        @Override
218
        public long getItemId(int i) {
219
            return i;
220
        }
221
 
222
        @Override
223
        public View getView(int i, View view, ViewGroup viewGroup) {
224
            ViewHolder viewHolder;
225
            // General ListView optimization code.
226
            if (view == null) {
227
                view = mInflator.inflate(R.layout.listitem_device, null);
228
                viewHolder = new ViewHolder();
229
                viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
230
                viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
231
                view.setTag(viewHolder);
232
            } else {
233
                viewHolder = (ViewHolder) view.getTag();
234
            }
235
 
236
            BluetoothDevice device = mLeDevices.get(i);
237
            final String deviceName = device.getName();
238
            if (deviceName != null && deviceName.length() > 0)
239
                viewHolder.deviceName.setText(deviceName);
240
            else
241
                viewHolder.deviceName.setText(R.string.unknown_device);
242
            viewHolder.deviceAddress.setText(device.getAddress());
243
 
244
            return view;
245
        }
246
    }
247
 
248
    // Device scan callback.
249
    private BluetoothAdapter.LeScanCallback mLeScanCallback =
250
            new BluetoothAdapter.LeScanCallback() {
251
 
252
        @Override
253
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
254
            runOnUiThread(new Runnable() {
255
                @Override
256
                public void run() {
257
                    mLeDeviceListAdapter.addDevice(device);
258
                    mLeDeviceListAdapter.notifyDataSetChanged();
259
                }
260
            });
261
        }
262
    };
263
 
264
    static class ViewHolder {
265
        TextView deviceName;
266
        TextView deviceAddress;
267
    }
268
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.