配对设备未显示在列表中
Posted
技术标签:
【中文标题】配对设备未显示在列表中【英文标题】:Paired devices aren't shown on the list 【发布时间】:2019-08-05 05:22:03 【问题描述】:我是一个新的 android studio 用户。我正在尝试构建一个 BLE GATT 服务应用程序。该应用程序适用于未配对的设备。但是,当我尝试扫描已配对的设备时,就会出现问题。它没有显示在扫描中。
我没有使用 MainActivity,而是使用 DeviceScanActivity 作为我的 Main。这是那部分的sn-p:
public class DeviceScanActivity extends ListActivity
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
private static final long SCAN_PERIOD = 7500;
private static final int LOCATION_REQUEST = 255;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
// getActionBar().setTitle(R.string.title_devices);
getActionBar().setDisplayShowTitleEnabled(false);
mHandler = new Handler();
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (mBluetoothAdapter == null)
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.main, menu);
if (!mScanning)
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
else
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(
R.layout.actionbar_indeterminate_progress);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
switch (item.getItemId())
case R.id.menu_scan:
mLeDeviceListAdapter.clear();
scanLeDevice(true);
break;
case R.id.menu_stop:
scanLeDevice(false);
break;
return true;
@Override
protected void onStart()
super.onStart();
verifyPermissionAndScan();
if (!mBluetoothAdapter.isEnabled())
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
mBluetoothAdapter.stopLeScan(mLeScanCallback);
else
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
@Override
protected void onResume()
super.onResume();
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED)
finish();
return;
super.onActivityResult(requestCode, resultCode, data);
@Override
protected void onPause()
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
@Override
protected void onListItemClick(ListView l, View v, int position, long id)
final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
if (device == null) return;
final Intent intent = new Intent(this, DeviceControlActivity.class);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
if (mScanning)
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mScanning = false;
startActivity(intent);
private void scanLeDevice(final boolean enable)
if (enable && !mScanning)
mHandler.postDelayed(new Runnable()
@Override
public void run()
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
else
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
private class LeDeviceListAdapter extends BaseAdapter
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflater;
private HashMap<BluetoothDevice, Integer> mDevicesRssi = new HashMap<>();
public LeDeviceListAdapter()
super();
mLeDevices = new ArrayList<>();//i removed BluetoothDevice from the diamond bracket
mInflater = DeviceScanActivity.this.getLayoutInflater();
public void addDevice(BluetoothDevice device, int rssi)
if (mDevicesRssi.containsKey(device))
int oldRssi = mDevicesRssi.get(device);
if (Math.abs(oldRssi - rssi) > 2)
mDevicesRssi.put(device, rssi);
notifyDataSetChanged();
else
mDevicesRssi.put(device, rssi);
notifyDataSetChanged();
if(!mLeDevices.contains(device))
mLeDevices.add(device);
notifyDataSetChanged();
public BluetoothDevice getDevice(int position)
return mLeDevices.get(position);
public void clear()
mLeDevices.clear();
@Override
public int getCount()
return mLeDevices.size();
@Override
public Object getItem(int i)
return mLeDevices.get(i);
@Override
public long getItemId(int i)
return i;
@Override
public View getView(int i, View view, ViewGroup viewGroup)
ViewHolder viewHolder;
//
BluetoothDevice device = mLeDevices.get(i);
//
if (view == null)
view = mInflater.inflate(R.layout.listitem_device, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi);
viewHolder.deviceBonded = (TextView) view.findViewById(R.id.device_bonded);
view.setTag(viewHolder);
else
viewHolder = (ViewHolder) view.getTag();
final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 0)
viewHolder.deviceName.setText(deviceName);
else
viewHolder.deviceName.setText(R.string.unknown_device);
viewHolder.deviceAddress.setText(device.getAddress());
updateBondedState(device, viewHolder);
updateRssi(device, viewHolder);
return view;
private void updateBondedState(BluetoothDevice device, ViewHolder viewHolder)
switch(device.getBondState())
case BOND_NONE:
viewHolder.deviceBonded.setVisibility(View.INVISIBLE);
break;
case BOND_BONDING:
viewHolder.deviceBonded.setText(R.string.bonding_state);
viewHolder.deviceBonded.setVisibility(View.VISIBLE);
break;
case BOND_BONDED:
viewHolder.deviceBonded.setText(R.string.bonded_state);
viewHolder.deviceBonded.setVisibility(View.VISIBLE);
break;
private void updateRssi(BluetoothDevice device, ViewHolder viewHolder)
final int rssi = mDevicesRssi.get(device);
viewHolder.deviceRssi.setText(String.format("%s dBm", String.valueOf(rssi)));
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback()
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord)
runOnUiThread(new Runnable()
@Override
public void run()
mLeDeviceListAdapter.addDevice(device,rssi);
mLeDeviceListAdapter.notifyDataSetChanged();
);
;
static class ViewHolder
TextView deviceName;
TextView deviceAddress;
TextView deviceRssi;
TextView deviceBonded;
@TargetApi(23)
private void verifyPermissionAndScan()
if (ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED)
Toast.makeText(this, R.string.location_already_given, Toast.LENGTH_LONG);
else
requestPermissions(new String[] ACCESS_COARSE_LOCATION, LOCATION_REQUEST);
@Override
public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)
if (requestCode != LOCATION_REQUEST) return;
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED)
Toast.makeText(this, R.string.permission_allowed, Toast.LENGTH_LONG).show();
else
Toast.makeText(this, R.string.permission_not_allowed, Toast.LENGTH_LONG).show();
这是我的 DeviceControlActiviy 类文件:
public class DeviceControlActivity extends Activity
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";
private TextView mConnectionState;
private TextView mDataField;
private String mDeviceName;
private String mDeviceAddress;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.gatt_services_characteristics);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
((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().setDisplayShowTitleEnabled(false);
getActionBar().setDisplayHomeAsUpEnabled(true);
final Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
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();
// mBluetoothLeService.connect(mDeviceAddress);
@Override
public void onServiceDisconnected(ComponentName componentName)
mBluetoothLeService = null;
;
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))
displayGattServices(mBluetoothLeService.getSupportedGattServices());
else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
;
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 (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;
;
private void clearUI()
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.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);
@Override
protected void onDestroy()
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.gatt_services, menu);
if (mConnected)
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
else
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
switch(item.getItemId())
case R.id.menu_connect:
mBluetoothLeService.connect(mDeviceAddress);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
return super.onOptionsItemSelected(item);
private void updateConnectionState(final int resourceId)
runOnUiThread(new Runnable()
@Override
public void run()
mConnectionState.setText(resourceId);
);
private void displayData(String data)
if (data != null)
mDataField.setText(data);
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>>();
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>();
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);
SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
this,
gattServiceData,
android.R.layout.simple_expandable_list_item_2,
new String[] LIST_NAME, LIST_UUID,
new int[] android.R.id.text1, android.R.id.text2 ,
gattCharacteristicData,
android.R.layout.simple_expandable_list_item_2,
new String[] LIST_NAME, LIST_UUID,
new int[] android.R.id.text1, android.R.id.text2
);
mGattServicesList.setAdapter(gattServiceAdapter);
private static IntentFilter makeGattUpdateIntentFilter()
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
我完美地获得了未配对设备的设备名称、地址和 RSSI。但如果设备已经配对,它不会显示在设备列表中,如果我点击未配对设备列表中的设备,它也不会自动将设备与手机配对。我需要通过手机的 BT 设置手动完成。
【问题讨论】:
【参考方案1】:这会显示与手机配对的所有设备(即使当前未配对)
JAVA
for(BluetoothDevice device : BluetoothAdapter.getDefaultAdapter().getBondedDevices())
device.getName(); // name
device.getAddress();// Address
科特林
for (device in BluetoothAdapter.getDefaultAdapter().bondedDevices)
device.name // name
device.address// Address
希望这会有所帮助!
【讨论】:
感谢您的帮助。你能告诉我应该在哪里实现这个功能吗? @AndroidPotato 真的取决于你想在哪里显示它。您可以在初始化适配器的 sn-p 中添加它mLeDeviceListAdapter = new LeDeviceListAdapter(); setListAdapter(mLeDeviceListAdapter);
在创建新实例时将数组传递给适配器类以上是关于配对设备未显示在列表中的主要内容,如果未能解决你的问题,请参考以下文章