Search code examples
androidbluetoothandroid-bluetooth

Not getting callback to broadcast receiver while pairing and unpairing bluetooth device for paired/ unpaired


Here in below code I am discovering all available BLE devices and trying to pair and unpair device on request. But I am not getting callback in registered broadcast receiver.

public class DeviceConfigurationActivity extends AppCompatActivity {

    Context context;
    Toolbar toolbar;
    RecyclerView recyclerView;
    DeviceListAdapter mAdapter;
    ArrayList<BluetoothDevice> mList;
    RelativeLayout rlBack;
    
    //BLUETOOTH
    BluetoothAdapter bluetoothAdapter;
    Set<BluetoothDevice> pairedDevices;
    String deviceName, deviceHardwareAddress;
    ProgressBar progressBar;
    private Intent bluetoothSerialServiceIntent;
    boolean mBound = false;
    private BluetoothSerialService btService;
    String selectedWorkType = "";
    private int btDevicePosition;
    private BTDeviceEntity connectedDevice;
    private BluetoothDevice alreadyConnectedBTDevice;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_device_configuration);
        init();
    }
    
    public void init(){
        context = this;
        toolbar = findViewById(R.id.toolbar);
        recyclerView = findViewById(R.id.recycler_view);
        rlBack = findViewById(R.id.rl_back);
        progressBar = findViewById(R.id.progress_bar);
        mList = new ArrayList<>();
    
            //Method calling
            setListeners();
            setUpRecyclerView();
            setUpBluetooth();
    }

    private void setListeners() {
        rlBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }

    /**
     * BLUETOOTH SETUP
     */
    private void setUpBluetooth() {
        progressBar.setVisibility(View.VISIBLE);

        //GET BLUETOOTH DEFAULT ADAPTER AND START DISCOVERY
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        bluetoothAdapter.startDiscovery();
        
        if (bluetoothAdapter == null){
            Toast.makeText(context, "Device doesn't support Bluetooth", Toast.LENGTH_SHORT).show();
        }

        //CHECK IF BLUETOOTH IS ENABLED
        checkIfEnabled();

        //REGISTER FOR A BROADCASTS WHEN A DEVICE IS DISCOVERED
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(receiver, filter);


        //REGISTER FOR A BROADCASTS FOR A DEVICE STATE CHANGED
        IntentFilter intent = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        registerReceiver(mPairReceiver, intent);
    }

    private void setUpRecyclerView() {
        mAdapter = new DeviceListAdapter(context, mList, new DeviceListAdapter.DeviceListAdapterInterface() {
            @Override
            public void onConnect(BluetoothDevice device, int position) {
                onConnection(device, position);
            }
        });
        recyclerView.setLayoutManager(new LinearLayoutManager(context));
        recyclerView.setAdapter(mAdapter);
    }


    //CHECK IF ENABLED
    private void checkIfEnabled() {
        if (!bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, 0);
            //Toast.makeText(getApplicationContext(), "Turned on", Toast.LENGTH_LONG).show();
        }else {
            //Toast.makeText(getApplicationContext(), "Already on", Toast.LENGTH_LONG).show();
        }
    }

    private void onConnection(BluetoothDevice device, int position) {
        //connectedDevice = device;
        btDevicePosition = position;
        if (device.getBondState() != Constants.STATE_DISCONNECTED) {
            new AlertDialog.Builder(context)
                    .setTitle("Connect to device")
                    .setMessage("Are you sure you want to connect to " + device.getName() + " ?")
                    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            pairDevice(device);
                            dialog.dismiss();
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    }).show();
        } else {
            new AlertDialog.Builder(context)
                    .setTitle("Disconnect from device")
                    .setMessage("Are you sure you want to disconnect from " + device.getName() + " ?")
                    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            unpairDevice(device);
                            dialog.dismiss();
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    }).show();
        }
    }

    private void pairDevice(BluetoothDevice device){
        Method method;
        try {
            method = device.getClass().getMethod("createBond", (Class[])null);
            method.invoke(device, (Object[]) null);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        mList.remove(btDevicePosition);
        mList.add(device);
        //mAdapter.updateAdapter(mList);

        //mAdapter.updateDeviceState(btDevicePosition, device.getBondState());
    }

    private void unpairDevice(BluetoothDevice device){
        Method method;
        try {
            method = device.getClass().getMethod("removeBond", (Class[])null);
            method.invoke(device, (Object[])null);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        mList.remove(btDevicePosition);
        mList.add(device);
        //mAdapter.updateAdapter(mList);

        //mAdapter.updateDeviceState(btDevicePosition, device.getBondState());
    }


    // Create a BroadcastReceiver for ACTION_FOUND.
    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent
                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            
                mList.add(device);

                //Set adapter
                Log.i("BT", device.getName() + "\n" + device.getAddress());
                progressBar.setVisibility(View.GONE);
                mAdapter.updateAdapter(mList);
            }
        }
    };

    private final BroadcastReceiver mPairReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
                final int prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);

                if (state == BluetoothDevice.BOND_BONDED && prevState == BluetoothDevice.BOND_BONDING) {
                    Toast.makeText(context, "Paired", Toast.LENGTH_SHORT).show();
                    // mAdapter.updateAdapter(mList);
                } else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDED) {
                    Toast.makeText(context, "Unpaired", Toast.LENGTH_SHORT).show();
                    // mAdapter.updateAdapter(mList);
                }

            }
        }
    };

    
    /**
     * HANDLER METHODS
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
        unregisterReceiver(mPairReceiver);
    }
}

Below is my adapter class for recycler view. Here also facing issue to update connected or disconnected update status.

public class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.MyViewHolder> {

    Context context;
    ArrayList<BluetoothDevice> mList;
    DeviceListAdapterInterface mListener;

    public interface DeviceListAdapterInterface{
        void onConnect(BluetoothDevice device, int position);
    }

    public void updateAdapter(ArrayList<BluetoothDevice> mList){
        this.mList = mList;
        notifyDataSetChanged();
    }

    public DeviceListAdapter(Context context, ArrayList<BluetoothDevice> mList,DeviceListAdapterInterface mListener) {
        this.context = context;
        this.mList = mList;
        this.mListener = mListener;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
        View view = LayoutInflater.from(context).inflate(R.layout.row_bt_device2, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, @SuppressLint("RecyclerView") int position) {
            BluetoothDevice model = mList.get(position);
            myViewHolder.txtDeviceName.setText(model.getName());

            if (model.getBondState() != Constants.STATE_DISCONNECTED){
                myViewHolder.txtConnectionStatus.setText("Connect");
            }else {
                myViewHolder.txtConnectionStatus.setText("Disconnect");
            }

            myViewHolder.txtConnectionStatus.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mListener.onConnect(model, position);
                }
            });
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {

        TextView txtDeviceName, txtConnectionStatus;
        ImageView imgIcon;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            txtDeviceName = itemView.findViewById(R.id.txt_device_name);
            txtConnectionStatus = itemView.findViewById(R.id.txt_connection_status);
            imgIcon = itemView.findViewById(R.id.img_icon);
        }
    }
}

Please suggest for solution. Any help will be appreciated. Thanks in advance.


Solution

  • Before startDiscovery() registerReciever.

    public BroadcastReceiver connectionCallbacks = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case BluetoothCommands.STATE_CONNECTING:
                    
                    break;
                case BluetoothCommands.STATE_CONNECTED:
                    
                    break;
                
                case BluetoothCommands.STATE_DISCONNECTED:
                    
                    break;
                
                case BluetoothDevice.ACTION_FOUND:
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    
                //From here you can add devices to your list.
    
                    break;
    
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                    if (intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR) == BluetoothDevice.BOND_BONDED) {
                        
                    }
                    break;
            }
        }
    };
    

    In pairDevice method call

    device.createBond();

    Register with these actions.

    public IntentFilter getConnectionIntentFilter() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothCommands.STATE_CONNECTING);
        intentFilter.addAction(BluetoothCommands.STATE_CONNECTED);
        intentFilter.addAction(BluetoothCommands.STATE_DISCONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        return intentFilter;
    }