LeScanner 在前台服务运行时 1 分钟后停止扫描

问题描述 投票:0回答:1

我想让 Ble Beacon Scanner 在前台运行,而不打开应用程序 UI。但是,当我运行服务并退出应用程序(但不终止应用程序)时,扫描仅运行 1 分钟并停止扫描,但在我再次打开应用程序后,扫描仍在继续。当应用程序关闭时,该服务不会被终止,只是停止扫描。

class BleForegroundService: Service() {
    companion object {
        private const val CHANNEL_ID = "ble_scanner_channel"
        internal val TAG = BleForegroundService::class.java.simpleName
    }

    private lateinit var bluetoothManager: BluetoothManager
    private lateinit var bluetoothAdapter: BluetoothAdapter
    private lateinit var bluetoothLeScanner: BluetoothLeScanner
    private val scanSettings = ScanSettings.Builder()
        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
        .build()
    private var scannedDevice: Int = 0

    private var scanFilter = arrayListOf<ScanFilter>()

    private val leScanCallback = BleScanCallback { result ->
        Log.d(TAG, "Result : $result")
        scannedDevice++
    }

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()
        val notification = createNotification()
        startForeground(1, notification)

        Log.d(TAG, "Creating BleForegroundScanner")
        bluetoothManager = getSystemService(BluetoothManager::class.java)
        bluetoothAdapter = bluetoothManager.adapter
        bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner

        val addressFilter = ScanFilter.Builder()
            .setDeviceAddress("E3:C4:8D:05:54:CF")
            .build()

        scanFilter.add(addressFilter)
    }

    @SuppressLint("MissingPermission")
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d(TAG, "Starting Scanner")
        bluetoothLeScanner.startScan(scanFilter, scanSettings, leScanCallback)

        return START_NOT_STICKY
    }

    @SuppressLint("MissingPermission")
    override fun onDestroy() {
        Log.d(TAG, "Destroying BleForegroundScanner")
        bluetoothLeScanner.stopScan(leScanCallback)
        super.onDestroy()
    }

    private fun createNotification(): Notification {
        val notificationChannelId = CHANNEL_ID

        // depending on the Android API that we're dealing with we will have
        // to use a specific method to create the notification
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            val channel = NotificationChannel(
                notificationChannelId,
                "Endless Service notifications channel",
                NotificationManager.IMPORTANCE_HIGH
            ).let {
                it.description = "Endless Service channel"
                it.enableLights(true)
                it.lightColor = Color.RED
                it.enableVibration(true)
                it.vibrationPattern = longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
                it
            }
            notificationManager.createNotificationChannel(channel)
        }

        val pendingIntent: PendingIntent = Intent(this, MainActivity::class.java).let { notificationIntent ->
            PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
        }

        val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Notification.Builder(
            this,
            notificationChannelId
        ) else Notification.Builder(this)

        return builder
            .setContentTitle("BLE Beacon Scanner")
            .setContentText("Scanning for BLE beacons")
            .setContentIntent(pendingIntent)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setTicker("Ticker text")
            .setPriority(Notification.PRIORITY_HIGH) // for under android 26 compatibility
            .build()
    }
}

在 MainActivity 中我这样写来在前台启动服务

serviceIntent = Intent(this, BleForegroundService::class.java)
this.startForegroundService(serviceIntent)

我不知道是什么问题为什么扫描只持续1分钟就停止扫描。但服务并没有被杀死。

android kotlin bluetooth bluetooth-lowenergy
1个回答
0
投票

要在 Android 上扫描 BLE 信标,您的应用程序需要以下权限:

Android 11 及以下版本:

需要

ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 权限:这是因为 BLE 扫描可用于估计用户的位置。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

Android 12 及以上版本:

需要

ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATIONBLUETOOTH_SCAN 权限: 如果您正在扫描 BLE Beacon,仍然需要位置权限

<uses-permission android:name="android.permission.BLUETOOTH_SCAN">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

后台扫描(所有 Android 版本):

ACCESS_BACKGROUND_LOCATION 权限至关重要:即使应用程序不在前台,这也允许您的应用程序扫描信标。

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

请求位置权限时,您必须授予“始终允许”而不是“仅在使用应用程序时允许”。

注 1: 您不能同时请求 ACCESS_FINE_LOCATIONACCESS_BACKGROUND_LOCATION。您必须首先请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION,然后单独请求 ACCESS_BACKGROUND_LOCATION

注 2: 或者,如果您在 Android 12 及更高版本上扫描 BLE 设备(不是信标设备),则只需在 BLUETOOTH_SCAN 权限中添加标志

"neverForLocation"
即可。不需要其他权限。

<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
© www.soinside.com 2019 - 2024. All rights reserved.