I need to get phone rotation values similar to which we can get in Activities with Sensor orientation (ActivityInfo.SCREEN_ORIENTATION_SENSOR / android:screenOrientation="sensor").
But I need to get it in background (a foreground service or app process) when app may not be visible or screen turned off, that's why Display.rotation or Resources.configuration.orientation won't work in this case.
In this case OrientationEventListener can help and it works in background with screen turned off. But how to covert orientation value to rotation in the similar logic like it's done in Activities by default with Sensor orientation? So it would look the same and natural like in activities - config changes on orientation.
I implemented the following method but still it doesn't really the same and not that good as orientation changes in Activity.
// Orientation hysteresis amount used in rounding, in degrees
private const val ORIENTATION_HYSTERESIS = 5
class RotationLiveData(context: Context) : LiveData<Int>(
// initial rotation
context.getSystemService<DisplayManager>()!!.getDisplay(Display.DEFAULT_DISPLAY).rotation
) {
private val listener = object : OrientationEventListener(
context.applicationContext,
) {
private var orientationHistory = ORIENTATION_UNKNOWN
override fun onOrientationChanged(orientation: Int) {
if (orientation == ORIENTATION_UNKNOWN) return
val changeOrientation = if (orientationHistory == ORIENTATION_UNKNOWN) {
true
} else {
var dist = abs(orientation - orientationHistory)
dist = dist.coerceAtMost(360 - dist)
dist >= 45 + ORIENTATION_HYSTERESIS
}
if (changeOrientation) {
orientationHistory = (orientation + 45) / 90 * 90 % 360
val rotation = when (orientationHistory) {
0 -> Surface.ROTATION_0
90 -> Surface.ROTATION_270
180 -> return // Surface.ROTATION_180 ignore (activities also don't have it)
else -> Surface.ROTATION_90
}
if (rotation != value) {
value = rotation
}
}
}
}
override fun onActive() {
super.onActive()
listener.enable()
}
override fun onInactive() {
super.onInactive()
listener.disable()
}
}
How can I improve it? Is there any source how is it done in Activity to repeat the same logic?
One of the problem with this custom method that when you hold the phone normally in portrait orientation and put it on the desk (flat positioned) it may return landscape rotation caused by a little angle, when you expect to have it in the same portrait rotation. Sensor Screen Orientation for Activity doesn't have such issues. That's why I'm trying to repeat the same logic and get the same rotation values in such situations.