SensorManager unregisterListener doesn't work

76 views Asked by At

What I want to do is to read data from the proximity sensor when I answer a phone call. I can read data from the sensor when the state is OFFHOOK. However, when I end the phone call (state IDLE), the proximitySensorListener.stopSensors() code doesn't stop the sensor.

class CallStateReceiver : BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {

    var proximitySensorListener = ProximitySensorListener(context!!)
    if (context == null || intent == null) {
        return
    }

    if (intent.action == TelephonyManager.ACTION_PHONE_STATE_CHANGED) {
        when (intent.getStringExtra(TelephonyManager.EXTRA_STATE)) {
            TelephonyManager.EXTRA_STATE_RINGING -> {
                Toast.makeText(context, "Incoming Call", Toast.LENGTH_SHORT).show()
            }

            TelephonyManager.EXTRA_STATE_OFFHOOK -> {
                Toast.makeText(context, "Call in progress", Toast.LENGTH_SHORT).show()
               
                proximitySensorListener.startSensors()
                
            }

            TelephonyManager.EXTRA_STATE_IDLE -> {
                Toast.makeText(context, "Call ended", Toast.LENGTH_SHORT).show()
                proximitySensorListener.stopSensors()
            }
        }
    }
}
}

class ProximitySensorListener(private val context: Context) : SensorEventListener {
private var sensorManager: SensorManager =
    context.getSystemService(Context.SENSOR_SERVICE) as SensorManager

val proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)

 fun startSensors() {
    if (proximitySensor != null) {
        sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL)
    }
}

 fun stopSensors() {
    sensorManager.unregisterListener(this, proximitySensor)
}

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}


override fun onSensorChanged(event: SensorEvent?) {

    if (event?.sensor?.type == Sensor.TYPE_PROXIMITY) {
        val distance = event.values[0]

        if (distance < 5) {
            println("Off")
        } else {
            println("On")
        }
    }
}
}

If I start the sensor listener during a phone call and try to stop it with a delayed call, it works. In other words, the sensor stops with this code, but it's not the ideal solution:

 TelephonyManager.EXTRA_STATE_OFFHOOK -> {
                Toast.makeText(context, "Call in progress", Toast.LENGTH_SHORT).show()

                proximitySensorListener.startSensors()
                
                GlobalScope.launch { 
                    delay(3000L)
                    proximitySensorListener.stopSensors()
                }
            }

So, why is that doesn't work?

1

There are 1 answers

0
vasberc On

I don not know if there is a reason that you use every time new listener, but if is not important you can user always 1 listener and register/unregister it when you want.

    class CallStateReceiver : BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {

    
    if (context == null || intent == null) {
        return
    } else if(context != null && !ProximitySensorListener.isInitialized ) {
         //initialize the ProximitySensorListener's properties
         ProximitySensorListener.initSensor(context)
    }

    if (intent.action == TelephonyManager.ACTION_PHONE_STATE_CHANGED) {
        when (intent.getStringExtra(TelephonyManager.EXTRA_STATE)) {
            TelephonyManager.EXTRA_STATE_RINGING -> {
                Toast.makeText(context, "Incoming Call", Toast.LENGTH_SHORT).show()
            }

            TelephonyManager.EXTRA_STATE_OFFHOOK -> {
                Toast.makeText(context, "Call in progress", Toast.LENGTH_SHORT).show()
               
                ProximitySensorListener.startSensors()
                
            }

            TelephonyManager.EXTRA_STATE_IDLE -> {
                Toast.makeText(context, "Call ended", Toast.LENGTH_SHORT).show()
                ProximitySensorListener.stopSensors()
            }
        }
    }
}
}

//Changed to object to be singleton
object ProximitySensorListener : SensorEventListener {

private var sensorManager: SensorManager? = null        

var proximitySensor: Sensor? = null 

val isInitialized get() = sensorManager != null && proximitySensor != null

 fun initSensor(context: Context) {
     sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
     proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
 }

 fun startSensors() {
    if (proximitySensor != null) {
        sensorManager?.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL)
    }
}

 fun stopSensors() {
    sensorManager?.unregisterListener(this, proximitySensor)
}

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}


override fun onSensorChanged(event: SensorEvent?) {

    if (event?.sensor?.type == Sensor.TYPE_PROXIMITY) {
        val distance = event.values[0]

        if (distance < 5) {
            println("Off")
        } else {
            println("On")
        }
    }
}
}