developermypos / myPOS-SDK-Android

myPOS SDK Android enabling to integrate Apps with myPOS Card Terminals for Card Payments processing
45 stars 22 forks source link

Check connection state without dialog #11

Open neone35 opened 3 years ago

neone35 commented 3 years ago

I have indicator in appbar which shows current connection status (active or disconnected).

Currently when terminal has disconnected because of high distance from android device, indicator still shows that connection is active and it's not possible to update indicator into disconnected state with POSHandler.getInstance().isConnected.

Here's my main code which runs every 15s and after setPOSReadyListener triggered. First option with ic_calc_gray_24dp is never executed:

override fun onPrepareOptionsMenu(menu: Menu): Boolean {
        if (!mPOSHandler.isConnected) {
            menu.findItem(R.id.menu_option_pos).icon = ContextCompat.getDrawable(this, R.drawable.ic_calc_gray_24dp)
        } else {
            menu.findItem(R.id.menu_option_pos).icon = ContextCompat.getDrawable(this, R.drawable.ic_calc_active_24dp)
        }
        return super.onPrepareOptionsMenu(menu)
    }
developermypos commented 3 years ago

Hi,

Have you tried to register Broadcast Receiver with this intent filter BluetoothDevice.ACTION_ACL_DISCONNECTED?

You can find an example in MainActivity.java

neone35 commented 3 years ago

Thanks. Will try soon and report back

neone35 commented 3 years ago

Thanks, it works with this code:

private fun setPosListener() {
        mPOSHandler.setConnectionListener {
            mPosIsConnected = true
            try {
                unregisterReceiver(mBTStateBroadcastReceiver)
            } catch (e: Exception) {
                Logger.d("BT state broadcast receiver not registered: ${e.localizedMessage}")
            }
            invalidateOptionsMenu()
        }
    }

    override fun onPrepareOptionsMenu(menu: Menu): Boolean {
        if (!mPosIsConnected) {
            menu.findItem(R.id.menu_option_pos).icon =
                ContextCompat.getDrawable(this, R.drawable.ic_calc_gray_24dp)
        } else {
            menu.findItem(R.id.menu_option_pos).icon =
                ContextCompat.getDrawable(this, R.drawable.ic_calc_active_24dp)
        }
        return super.onPrepareOptionsMenu(menu)
    }

    private fun watchForBTStateBroadcasts() {
        val btStateFilter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
        mBTStateBroadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                val action = intent.action
                if (action == BluetoothAdapter.ACTION_STATE_CHANGED) {
                    val state = intent.getIntExtra(
                        BluetoothAdapter.EXTRA_STATE,
                        BluetoothAdapter.ERROR
                    )
                    when (state) {
                        BluetoothAdapter.STATE_OFF -> mBluetoothAdapter.enable()
                    }
                }
            }
        }
        registerReceiver(mBTStateBroadcastReceiver, btStateFilter)
    }

    private fun watchForPosBroadcasts() {
        mPosIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
        mPosIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)

        mPosBroadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                Logger.d("Received pos broadcast ${intent.action}")
                when (intent.action) {
                    BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
                        val device =
                            intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
                        if (POSHandler.getInstance().connectedDevice != null && device != null &&
                            POSHandler.getInstance().connectedDevice.address.equals(
                                device.address,
                                ignoreCase = true
                            )
                        ) {
                            mPosIsConnected = false
                            mBluetoothAdapter.disable()
                            watchForBTStateBroadcasts()
                            invalidateOptionsMenu()
                        }
                    }
                }
            }
        }
        registerReceiver(mPosBroadcastReceiver, mPosIntentFilter)
    }

Didn't manage to unpair device, so I restart BT when device is disconnected. Then on new connection attempt it's removed from connected list. Maybe there is correct way to unpair without restarting BT?