配对设备未显示在列表中

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); 在创建新实例时将数组传递给适配器类

以上是关于配对设备未显示在列表中的主要内容,如果未能解决你的问题,请参考以下文章

在布局中创建的列表视图中列出配对的蓝牙设备

屏幕固定模式下未显示蓝牙配对对话框

如何使用 Ionic 与另一个 BLE 设备配对?

求助,win10蓝牙显示已配对,但是没有连接

是否可以通过 OBEX 在未配对的设备之间传输文件?

android的蓝牙匹配连接