Search code examples
androidkotlinbluetoothbeacon

BluetoothLeScanner startScan() is not working without log


I had made app which scan beacon device.

And apparently it worked successfully.

I have not modified the code related to this.

But today, I tried scanning today, It didn't work!

It just left log start scanand scan timeout.

here is my code.

ScanViewModel.kt

class ScanViewModel(application: Application) : AndroidViewModel(application) {

    companion object{
        private const val TAG = "ScanViewModel"
        private const val UUID = "01122334-4556-6778-899a-abbccddeeff0"
        private const val MIN_RSSI = -85
    }

    private var isScanning = false

    private val bluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE) {
        val bluetoothManager = application.
            getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        bluetoothManager.adapter
    }

    private val BluetoothAdapter.isDisabled: Boolean
        get() = !isEnabled

    private val handler = Handler()

    private var runnable = Runnable {
        isScanning = false
        bluetoothAdapter!!.bluetoothLeScanner.stopScan(scanCallback)
        Log.d(TAG, "Scan Timeout")
    }

    fun isBluetoothOn(): Boolean {
        return bluetoothAdapter!!.isDisabled
    }

    fun startScan(time: Long) {
        handler.postDelayed(runnable, time)
        isScanning = true
        bluetoothAdapter!!.bluetoothLeScanner.startScan(scanCallback)
        Log.d(TAG, "Scan is started")
    }

    fun stopScan() {
        isScanning = false
        bluetoothAdapter!!.bluetoothLeScanner.stopScan(scanCallback)
        Log.d(TAG, "Scan is terminated")
    }

    private val scanCallback = object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult?) {
            super.onScanResult(callbackType, result)

            result?.let { it ->
                Log.d(TAG, "find : ${result.device}")

                if (it.rssi < MIN_RSSI) {
                    Log.d(TAG, "rssi (${it.rssi}) is too week. return")
                    return
                }

                if (it.scanRecord == null) {
                    Log.d(TAG, "This device does not have scanRecord. return")
                    return
                }

                val bleDevice = BleCreater.create(it.device, it.rssi, it.scanRecord!!.bytes)

                Log.d(TAG, "uuid : ${bleDevice!!.uuid}, major : ${bleDevice.major}, minor : ${bleDevice.minor}, ${bleDevice.rssi}")

                if (bleDevice.uuid == UUID) {
                    Log.d(TAG, "H/W has been found")

                    stopScan()

                    return
                }
            }
        }

        override fun onBatchScanResults(results: MutableList<ScanResult>?) {
            super.onBatchScanResults(results)
        }

        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)
        }
    }
}

ScanActivity

class ScanActivity : BaseActivity<ActivityScanBinding>(R.layout.activity_scan) {
    private lateinit var vm: ScanViewModel
    private lateinit var viewModelFactory: ViewModelProvider.AndroidViewModelFactory

    private companion object {
        const val SCAN_PERIOD = 10000L
        const val REQUEST_ENABLE_BT = 1000
        const val TAG = "ScanActivity"

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModelFactory = ViewModelProvider.AndroidViewModelFactory(application)
        vm = ViewModelProvider(this, viewModelFactory).get(ScanViewModel::class.java)

        if (BluetoothUtil.isBluetoothAvailable(this)) {
            Log.d(TAG, "This device does not support Bluetooth.")
            finish()
        } else {
            Log.d(TAG, "This device supports Bluetooth.")
        }

        setSupportActionBar(binding.toolbarScan)

        supportActionBar?.let {
            it.setDisplayShowTitleEnabled(false)
            it.setDisplayHomeAsUpEnabled(true)
            it.setHomeAsUpIndicator(R.drawable.ic_keyboard_arrow_left_white_32dp)
        }
    }

    override fun onResume() {
        super.onResume()

        if (vm.isBluetoothOn()) {
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)

        } else {

            vm.startScan(SCAN_PERIOD)
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (item.itemId == android.R.id.home) {
            vm.stopScan()
            finish()
            return true
        }
        return super.onOptionsItemSelected(item)
    }
}

As you can see, ScanCallback has some log. I've seen it for sure in logcat!!

but now, I can see only this log.

2020-05-29 00:42:55.895 21880-21880 D/ViewRootImpl@4646843[MainActivity]: ViewPostIme pointer 0
2020-05-29 00:42:56.054 21880-21880 D/ViewRootImpl@4646843[MainActivity]: ViewPostIme pointer 1
2020-05-29 00:42:56.092 21880-21880 W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@ae4800e
2020-05-29 00:42:56.111 21880-21880 I/MultiWindowDecorSupport: updateCaptionType >> DecorView@b569840[], isFloating: false, isApplication: true, hasWindowDecorCaption: false, hasWindowControllerCallback: true
2020-05-29 00:42:56.112 21880-21880 D/MultiWindowDecorSupport: setCaptionType = 0, DecorView = DecorView@b569840[]
2020-05-29 00:42:56.147 21880-21880 D/ScanActivity: This device supports Bluetooth.
2020-05-29 00:42:56.166 21880-21880 D/BluetoothAdapter: STATE_ON
2020-05-29 00:42:56.166 21880-21880 I/chatty: uid=10908(com.seoultech.livingtogether_android) identical 1 line
2020-05-29 00:42:56.167 21880-21880 D/BluetoothAdapter: STATE_ON
2020-05-29 00:42:56.168 21880-21880 D/BluetoothAdapter: BLE support array set: 010011
2020-05-29 00:42:56.168 21880-21880 D/BluetoothLeScanner: Start Scan with callback
2020-05-29 00:42:56.170 21880-21900 D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=12 mScannerId=0
2020-05-29 00:42:56.175 21880-21880 D/ScanViewModel: Scan is started
2020-05-29 00:42:56.181 21880-21880 D/ViewRootImpl@e2f6c46[ScanActivity]: setView = com.android.internal.policy.DecorView@b569840 TM=true MM=false
2020-05-29 00:42:56.184 21880-21880 D/ViewRootImpl@4646843[MainActivity]: MSG_WINDOW_FOCUS_CHANGED 0 1
2020-05-29 00:42:56.185 21880-21880 D/InputMethodManager: prepareNavigationBarInfo() DecorView@b68fe3a[MainActivity]
2020-05-29 00:42:56.185 21880-21880 D/InputMethodManager: getNavigationBarColor() -855310
2020-05-29 00:42:56.200 21880-21880 D/ViewRootImpl@e2f6c46[ScanActivity]: Relayout returned: old=(0,0,1080,2220) new=(0,0,1080,2220) req=(1080,2220)0 dur=7 res=0x7 s={true 524632977408} ch=true
2020-05-29 00:42:56.201 21880-21925 D/OpenGLRenderer: createReliableSurface : 0x7a1deda640, 0x7a268ff000
2020-05-29 00:42:56.202 21880-21925 D/mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
2020-05-29 00:42:56.217 21880-21929 D/FA: Connected to remote service
2020-05-29 00:42:56.234 21880-21880 D/ViewRootImpl@e2f6c46[ScanActivity]: MSG_WINDOW_FOCUS_CHANGED 1 1
2020-05-29 00:42:56.234 21880-21880 D/InputMethodManager: prepareNavigationBarInfo() DecorView@b569840[ScanActivity]
2020-05-29 00:42:56.234 21880-21880 D/InputMethodManager: getNavigationBarColor() -855310
2020-05-29 00:42:56.236 21880-21880 D/InputMethodManager: prepareNavigationBarInfo() DecorView@b569840[ScanActivity]
2020-05-29 00:42:56.236 21880-21880 D/InputMethodManager: getNavigationBarColor() -855310
2020-05-29 00:42:56.236 21880-21880 D/InputMethodManager: startInputInner - Id : 0
2020-05-29 00:42:56.236 21880-21880 I/InputMethodManager: startInputInner - mService.startInputOrWindowGainedFocus
2020-05-29 00:42:56.237 21880-21880 D/InputTransport: Input channel destroyed: 'ClientS', fd=84
2020-05-29 00:42:56.260 21880-21880 D/ViewRootImpl@e2f6c46[ScanActivity]: MSG_RESIZED: frame=(0,0,1080,2220) ci=(0,63,0,126) vi=(0,63,0,126) or=1
2020-05-29 00:42:56.543 21880-21925 W/libEGL: EGLNativeWindowType 0x7a1deda790 disconnect failed
2020-05-29 00:42:56.547 21880-21880 D/ViewRootImpl@4646843[MainActivity]: Relayout returned: old=(0,0,1080,2220) new=(0,0,1080,2220) req=(1080,2220)8 dur=4 res=0x5 s={false 0} ch=true
2020-05-29 00:42:56.550 21880-21880 D/ViewRootImpl@4646843[MainActivity]: stopped(true) old=false
2020-05-29 00:42:56.562 21880-21880 D/ViewRootImpl@4646843[MainActivity]: Relayout returned: old=(0,0,1080,2220) new=(0,0,1080,2220) req=(1080,2220)8 dur=4 res=0x5 s={false 0} ch=false
2020-05-29 00:43:02.899 21880-21886 I/ogether_androi: Compiler allocated 4162KB to compile void android.view.ViewRootImpl.performTraversals()
2020-05-29 00:43:06.185 21880-21880 D/BluetoothAdapter: STATE_ON
2020-05-29 00:43:06.187 21880-21880 D/BluetoothAdapter: STATE_ON
2020-05-29 00:43:06.187 21880-21880 D/BluetoothLeScanner: Stop Scan with callback
2020-05-29 00:43:06.194 21880-21880 D/ScanViewModel: Scan Timeout

No log, No exception. So I can not find out problem.

I re-executed the code I last succeeded with using the git, but the result was the same.

I'm using Android 10 then and now.

Help me.


Solution

  • A few troubleshooting tips:

    1. Do you know that a bluetooth device is advertising? Try an off-the-shelf app like nRf Connect and make sure one is detected.

    2. Is your bluetooth stack in a bad state? If so, you may not be able to detect anything in step 1. Turning bluetooth off and on, or rebooting your phone may fix it.

    3. Did you dynamically request and obtain location permission from the user? You cannot detect beacons unless you do so. Read here.

    4. If you check app permissions does it confirm that location permission has been granted to your app? Go to Settings -> Applications -> Your App and check the granted permissions.

    5. Is bluetooth turned on in phone settings?

    6. Is location turn on in phone settings?