(Un)register sensor listener in an Android service not always working
(Un)register sensor listener in an Android service not always working
我创建了一个监听设备加速度计的自定义服务,我希望能够暂停传感器读数。有两种情况我想暂停传感器读数,第一种是 GUI 中的暂停按钮暂停所有传感器(现在我刚刚实现了加速度计,但更多传感器将随之而来),第二种是传感器在应用程序设置。我使用一个 observable 来观察调用 unregisterSensors() 函数的暂停按钮的 App 设置和 Intent 的变化(参见下面的代码)。这首先在应用程序上运行良好 运行,但当我关闭并重新打开该应用程序时,行为变得很奇怪。从应用程序设置中注销侦听器始终有效,但在使用 GUI 中的暂停按钮时突然不起作用,即使确实调用了 unregisterSensors() 函数(意图工作正常)。如果我强制应用程序退出 Android 设置或 Android 工作室并重新启动它,我又会出现正常行为,但不像从多任务栏中删除应用程序时所说的那样。这是服务的相关代码 class:
class SensorService: Service(), SensorEventListener {
private var sensorAccelerometer: Sensor? = null
private var sensorLinearAccelerometer: Sensor? = null
private lateinit var sensorManager: SensorManager
companion object {
var isServiceStarted = false
var recordAccelerometer = MutableLiveData<Boolean>().apply { value = true }
}
override fun onCreate() {
super.onCreate()
sensorManager = applicationContext.getSystemService(Context.SENSOR_SERVICE) as SensorManager
recordAccelerometer.observeForever { value ->
if (sensorAccelerometer != null) {
// Always works
if (value) {
sensorAccelerometer?.also {acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
sensorLinearAccelerometer?.also { acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
} else {
sensorManager.unregisterListener(this, sensorAccelerometer)
sensorManager.unregisterListener(this, sensorLinearAccelerometer)
}
}
}
isServiceStarted = true
}
override fun onDestroy() {
super.onDestroy()
// Unregister sensors
unregisterSensors()
isServiceStarted = false
}
private fun registerSensors() {
// Register sensors
if (availableSensors["accelerometer"]!! && recordAccelerometer.value!!) {
sensorAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorLinearAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)
sensorAccelerometer?.also {acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
sensorLinearAccelerometer?.also { acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
}
}
private fun unregisterSensors() {
// Unregister sensors
// Works not after closing and opening the app
sensorManager.unregisterListener(this, sensorAccelerometer)
sensorManager.unregisterListener(this, sensorLinearAccelerometer)
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
// Stop service unless sensors are being recorded
stopSelf(1)
}
}
有人可能知道问题出在哪里吗?我看不出调用可能导致此问题的 sensorManager.unregisterListener(...) 有任何区别。
所以如果未来的人遇到同样的问题,我现在找到了解决办法。问题是我在我的 activity 中绑定到这个服务,并且每次绑定到它时绑定服务 return 一个新实例。因此,确实使用了不同的事件监听器,正如@greeble31 已经假设的那样。由于我需要绑定到服务,我现在使用 LiveData register/unregister 传感器。
accelerometerRegistered.observeForever { value ->
if (value) {
sensorAccelerometer?.also {acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
} else {
sensorManager.unregisterListener(this, sensorAccelerometer)
}
}
LiveData 对象在伴随对象中定义,因此我可以在服务内外更改它 class。
我创建了一个监听设备加速度计的自定义服务,我希望能够暂停传感器读数。有两种情况我想暂停传感器读数,第一种是 GUI 中的暂停按钮暂停所有传感器(现在我刚刚实现了加速度计,但更多传感器将随之而来),第二种是传感器在应用程序设置。我使用一个 observable 来观察调用 unregisterSensors() 函数的暂停按钮的 App 设置和 Intent 的变化(参见下面的代码)。这首先在应用程序上运行良好 运行,但当我关闭并重新打开该应用程序时,行为变得很奇怪。从应用程序设置中注销侦听器始终有效,但在使用 GUI 中的暂停按钮时突然不起作用,即使确实调用了 unregisterSensors() 函数(意图工作正常)。如果我强制应用程序退出 Android 设置或 Android 工作室并重新启动它,我又会出现正常行为,但不像从多任务栏中删除应用程序时所说的那样。这是服务的相关代码 class:
class SensorService: Service(), SensorEventListener {
private var sensorAccelerometer: Sensor? = null
private var sensorLinearAccelerometer: Sensor? = null
private lateinit var sensorManager: SensorManager
companion object {
var isServiceStarted = false
var recordAccelerometer = MutableLiveData<Boolean>().apply { value = true }
}
override fun onCreate() {
super.onCreate()
sensorManager = applicationContext.getSystemService(Context.SENSOR_SERVICE) as SensorManager
recordAccelerometer.observeForever { value ->
if (sensorAccelerometer != null) {
// Always works
if (value) {
sensorAccelerometer?.also {acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
sensorLinearAccelerometer?.also { acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
} else {
sensorManager.unregisterListener(this, sensorAccelerometer)
sensorManager.unregisterListener(this, sensorLinearAccelerometer)
}
}
}
isServiceStarted = true
}
override fun onDestroy() {
super.onDestroy()
// Unregister sensors
unregisterSensors()
isServiceStarted = false
}
private fun registerSensors() {
// Register sensors
if (availableSensors["accelerometer"]!! && recordAccelerometer.value!!) {
sensorAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorLinearAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)
sensorAccelerometer?.also {acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
sensorLinearAccelerometer?.also { acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
}
}
private fun unregisterSensors() {
// Unregister sensors
// Works not after closing and opening the app
sensorManager.unregisterListener(this, sensorAccelerometer)
sensorManager.unregisterListener(this, sensorLinearAccelerometer)
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
// Stop service unless sensors are being recorded
stopSelf(1)
}
}
有人可能知道问题出在哪里吗?我看不出调用可能导致此问题的 sensorManager.unregisterListener(...) 有任何区别。
所以如果未来的人遇到同样的问题,我现在找到了解决办法。问题是我在我的 activity 中绑定到这个服务,并且每次绑定到它时绑定服务 return 一个新实例。因此,确实使用了不同的事件监听器,正如@greeble31 已经假设的那样。由于我需要绑定到服务,我现在使用 LiveData register/unregister 传感器。
accelerometerRegistered.observeForever { value ->
if (value) {
sensorAccelerometer?.also {acceleration ->
sensorManager.registerListener(this, acceleration, SensorManager.SENSOR_DELAY_FASTEST)
}
} else {
sensorManager.unregisterListener(this, sensorAccelerometer)
}
}
LiveData 对象在伴随对象中定义,因此我可以在服务内外更改它 class。