@@ -5,125 +5,118 @@ import android.hardware.Sensor
55import android.hardware.SensorEvent
66import android.hardware.SensorEventListener
77import android.hardware.SensorManager
8+ import android.view.OrientationEventListener
89import com.facebook.react.bridge.ReactApplicationContext
910
1011class OrientationSensorsEventListener (
1112 context : ReactApplicationContext ,
12- ) : SensorEventListener {
13+ ) : SensorEventListener, OrientationEventListener(context, SensorManager .SENSOR_DELAY_UI ) {
14+ private val rotationMatrix = FloatArray (9 )
15+
1316 private var mSensorManager: SensorManager =
1417 context.getSystemService(SENSOR_SERVICE ) as SensorManager
15-
1618 private var mRotationSensor: Sensor ? =
1719 mSensorManager.getDefaultSensor(Sensor .TYPE_ROTATION_VECTOR )
18- private var mAccelerometerSensor: Sensor ? =
19- mSensorManager.getDefaultSensor(Sensor .TYPE_ACCELEROMETER )
20- private var mMagneticFieldSensor: Sensor ? =
21- mSensorManager.getDefaultSensor(Sensor .TYPE_MAGNETIC_FIELD )
22-
2320 private var hasRotationSensor: Boolean =
24- mRotationSensor != null
25- private var hasAccelerometerAndMagneticFieldSensors: Boolean =
26- mAccelerometerSensor != null && mMagneticFieldSensor != null
21+ mRotationSensor != null
2722
28- private val accelerometerReading = FloatArray (3 )
29- private val magnetometerReading = FloatArray (3 )
30-
31- private var lastComputedOrientationAngles = FloatArray (3 )
32- private var onOrientationAnglesChangedCallback: ((orientationAngles: FloatArray ) -> Unit )? = null
33-
34- fun setOnOrientationAnglesChangedCallback (callback : (orientation: FloatArray ) -> Unit ) {
35- onOrientationAnglesChangedCallback = callback
36- }
37-
38- override fun onSensorChanged (event : SensorEvent ? ) {
39- if (event == null ) {
40- return
41- }
42-
43- if (event.sensor.type == Sensor .TYPE_ROTATION_VECTOR ) {
44- computeOrientationFromRotationSensor(event.values);
45- return
46- }
23+ private var lastComputedDeviceOrientation = Orientation .UNKNOWN
24+ private var lastComputedFaceOrientation = Orientation .UNKNOWN
4725
48- computeOrientationFromOtherSensors(event)
26+ private var onDeviceOrientationChangedCallback: ((deviceOrientation: Orientation ) -> Unit )? = null
27+ fun setOnDeviceOrientationChangedCallback (callback : (deviceOrientation: Orientation ) -> Unit ) {
28+ onDeviceOrientationChangedCallback = callback
4929 }
5030
51- override fun onAccuracyChanged (sensor : Sensor ? , accuracy : Int ) {}
31+ override fun enable () {
32+ super .enable()
5233
53- fun enable () {
5434 if (hasRotationSensor) {
5535 mSensorManager.registerListener(
5636 this ,
5737 mRotationSensor,
5838 SensorManager .SENSOR_DELAY_NORMAL ,
5939 SensorManager .SENSOR_DELAY_UI
6040 )
61- return
6241 }
6342
64- if (hasAccelerometerAndMagneticFieldSensors) {
65- mSensorManager.registerListener(
66- this ,
67- mAccelerometerSensor,
68- SensorManager .SENSOR_DELAY_NORMAL ,
69- SensorManager .SENSOR_DELAY_UI
70- )
71- mSensorManager.registerListener(
72- this ,
73- mMagneticFieldSensor,
74- SensorManager .SENSOR_DELAY_NORMAL ,
75- SensorManager .SENSOR_DELAY_UI
76- )
77- return
78- }
43+ lastComputedDeviceOrientation = Orientation .UNKNOWN
44+ lastComputedFaceOrientation = Orientation .UNKNOWN
7945 }
8046
81- fun disable () {
82- mSensorManager.unregisterListener(this )
83- }
84-
85- private fun computeOrientationFromRotationSensor (values : FloatArray ) {
86- val rotationMatrix = FloatArray (9 )
87- SensorManager .getRotationMatrixFromVector(rotationMatrix, values)
47+ override fun disable () {
48+ super .disable()
8849
89- val orientationAngles = FloatArray (3 )
90- SensorManager .getOrientation(rotationMatrix, orientationAngles)
50+ if (hasRotationSensor) {
51+ mSensorManager.unregisterListener(this )
52+ }
9153
92- notifyOrientationAnglesChanged(orientationAngles)
54+ lastComputedDeviceOrientation = Orientation .UNKNOWN
55+ lastComputedFaceOrientation = Orientation .UNKNOWN
9356 }
9457
95- private fun computeOrientationFromOtherSensors (event : SensorEvent ) {
96- if (event.sensor.type == Sensor .TYPE_ACCELEROMETER ) {
97- System .arraycopy(event.values, 0 , accelerometerReading, 0 , accelerometerReading.size)
58+ override fun onOrientationChanged (angleDegrees : Int ) {
59+ if (angleDegrees == ORIENTATION_UNKNOWN ) {
60+ lastComputedDeviceOrientation = Orientation .UNKNOWN
61+ return
9862 }
9963
100- if (event.sensor.type == Sensor .TYPE_MAGNETIC_FIELD ) {
101- System .arraycopy(event.values, 0 , magnetometerReading, 0 , magnetometerReading.size)
64+ val currentDeviceOrientation = when (angleDegrees) {
65+ in LANDSCAPE_RIGHT_START .. LANDSCAPE_RIGHT_END -> Orientation .LANDSCAPE_RIGHT
66+ in PORTRAIT_UPSIDE_DOWN_START .. PORTRAIT_UPSIDE_DOWN_END -> Orientation .PORTRAIT_UPSIDE_DOWN
67+ in LANDSCAPE_LEFT_START .. LANDSCAPE_LEFT_END -> Orientation .LANDSCAPE_LEFT
68+ else -> Orientation .PORTRAIT
10269 }
10370
104- val rotationMatrix = FloatArray (9 )
105- val didComputeMatrix = SensorManager .getRotationMatrix(
106- rotationMatrix,
107- null ,
108- accelerometerReading,
109- magnetometerReading
110- )
111- if (! didComputeMatrix) {
71+ if (currentDeviceOrientation == lastComputedDeviceOrientation) return
72+
73+ notifyDeviceOrientationChanged(currentDeviceOrientation)
74+ }
75+
76+ override fun onSensorChanged (event : SensorEvent ) {
77+ if (event.sensor.type != Sensor .TYPE_ROTATION_VECTOR ) return
78+
79+ if (lastComputedDeviceOrientation != Orientation .UNKNOWN ) {
80+ lastComputedFaceOrientation = Orientation .UNKNOWN
11281 return
11382 }
11483
115- val orientationAngles = FloatArray (3 )
116- SensorManager .getOrientation(rotationMatrix, orientationAngles)
84+ SensorManager .getRotationMatrixFromVector(rotationMatrix, event.values)
85+
86+ val zUp = rotationMatrix[8 ]
87+ val currentFaceOrientation = when {
88+ zUp > FACE_UP_Z_THRESHOLD -> Orientation .FACE_UP
89+ zUp < - FACE_DOWN_Z_THRESHOLD -> Orientation .FACE_DOWN
90+ else -> null
91+ }
92+
93+ if (currentFaceOrientation == null ) return
94+
95+ if (currentFaceOrientation == lastComputedFaceOrientation) return
11796
118- notifyOrientationAnglesChanged(orientationAngles )
97+ notifyFaceOrientationChanged(currentFaceOrientation )
11998 }
12099
121- private fun notifyOrientationAnglesChanged (orientationAngles : FloatArray ) {
122- if (lastComputedOrientationAngles.contentEquals(orientationAngles)) {
123- return
124- }
100+ private fun notifyDeviceOrientationChanged (deviceOrientation : Orientation ) {
101+ lastComputedDeviceOrientation = deviceOrientation
102+ onDeviceOrientationChangedCallback?.invoke(deviceOrientation)
103+ }
104+
105+ private fun notifyFaceOrientationChanged (faceOrientation : Orientation ) {
106+ lastComputedFaceOrientation = faceOrientation
107+ onDeviceOrientationChangedCallback?.invoke(faceOrientation)
108+ }
125109
126- onOrientationAnglesChangedCallback?.invoke(orientationAngles)
127- lastComputedOrientationAngles = orientationAngles
110+ override fun onAccuracyChanged (sensor : Sensor ? , accuracy : Int ) = Unit
111+
112+ companion object {
113+ private const val LANDSCAPE_RIGHT_START = 45
114+ private const val LANDSCAPE_RIGHT_END = 134
115+ private const val PORTRAIT_UPSIDE_DOWN_START = 135
116+ private const val PORTRAIT_UPSIDE_DOWN_END = 224
117+ private const val LANDSCAPE_LEFT_START = 225
118+ private const val LANDSCAPE_LEFT_END = 314
119+ private const val FACE_UP_Z_THRESHOLD = 0.906f
120+ private const val FACE_DOWN_Z_THRESHOLD = 0.906f
128121 }
129122}
0 commit comments