Author: Huang Longfei, engineer of Agora

preface

When using mobile phones in our daily life, we usually encounter the following two scenarios. Scenario 1: When the mobile phone is used to watch a video and the automatic rotation of the screen is enabled, the effect is different when the mobile phone is held horizontally or vertically. The display in portrait mode is shown in the figure below (Figure 1), and in landscape mode is shown in Figure 2.

Figure 1. Video playback in portrait

Figure 2. Play video in landscape

Scenario 2: In the mobile phone application, certain interfaces of certain applications display different interface effects according to the current horizontal and vertical screen status, which is convenient for users to use. For example, the meeting interface in AgoraVideoCall is shown in Figure 3 and Figure 4:

Figure 3.AgoraVideoCall conference interface displayed in portrait

Figure 4. The AgoraVideoCall conference interface is displayed in horizontal screen

In both of these scenarios, the user automatically identifies whether they want a landscape or portrait display based on how they hold the phone and how they rotate it. The question of “how the mobile phone can identify the user’s intention according to the user’s rotation action” will be elaborated in detail in the following article.

Principle of acceleration sensor

The core component of mobile phone to achieve this function is the acceleration sensor. Before introducing the acceleration sensor, we should first understand the coordinate system of the sensor.

  • Sensor coordinate system

Typically, sensor frameworks use a standard 3-axis coordinate system to represent data values. For most sensors, the coordinate system is defined relative to the device screen when the device is in the default screen orientation (see Figure 5). When the device is in the default screen orientation, the X axis extends horizontally to the right, Y axis extends vertically up, and Z axis extends vertically out of the screen. In this coordinate system, the coordinates behind the screen will have a negative Z value. A special point to note about this coordinate system is that the coordinate system of the sensor does not change as the device moves.

Figure 5. Sensor coordinate system (relative to the device)

Acceleration sensor

Acceleration sensor, it uses elastic sensor made of cantilever displacement, and the energy storage spring made of elastic sensor to drive the electrical contact, complete the conversion from gravity changes to electrical signals. For example, a shell and an object to measure acceleration, connected by a spring, form a gravity sensor. When we move the shell up, the metal ball will pull the spring down because of inertia. Then we only need to measure the tension of the spring, and we can calculate the gravity. So you can easily get an X, Y, Z accelerometer, and you can measure the direction of motion of an object in three dimensions. See [Principle of Gravity sensing] for details.

Acceleration sensor is widely used in mobile devices. This paper mainly introduces the application of acceleration sensor in horizontal and vertical screen switching in Android system. Its principle is mainly as follows: by monitoring the acceleration sensor, the acceleration value of X, Y and Z directions can be obtained in real time; When 4(XX + YY)>=Z*Z, the rotation Angle of the device on the X and Y planes is calculated. Finally, the horizontal and vertical screen state of the equipment is calculated according to the rotation Angle. The main code is posted below.

/** * Override protected void onResume() {super.onresume (); orientationListener = new OrientationListener(this); orientationListener.enable(); } public void enable() { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Not enabled"); return; } if (mEnabled == false) { if (localLOGV) Log.d(TAG, "OrientationEventListener enabled"); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); mEnabled = true; }}Copy the code
class SensorEventListenerImpl implements SensorEventListener { private static final int _DATA_X = 0; private static final int _DATA_Y = 1; private static final int _DATA_Z = 2; /** ** Calculate the rotation Angle of the device by changing the acceleration values in the X, Y, and Z directions. **/ public void onSensorChanged(SensorEvent event) { float[] values = event.values; int orientation = ORIENTATION_UNKNOWN; float X = -values[_DATA_X]; float Y = -values[_DATA_Y]; float Z = -values[_DATA_Z]; float magnitude = X*X + Y*Y; // Don't trust the angle if the magnitude is small compared to the y value if (magnitude * 4 >= Z*Z) { float OneEightyOverPi = 57.29577957855 f; float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi; orientation = 90 - (int)Math.round(angle); // normalize to 0 - 359 range while (orientation >= 360) { orientation -= 360; } while (orientation < 0) { orientation += 360; } } if (mOldListener ! = null) { mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values); } if (orientation ! = mOrientation) { mOrientation = orientation; onOrientationChanged(orientation); }}}Copy the code
public class OrientationListener extends OrientationEventListener { private int degree = 0; Private int mOrientation = 0; Public unknown OrientationListener(Context Context) {super(Context); } @override public void onOrientationChanged(int orientation) {degree = orientation; if (degree > 0 && degree < 45) { mOrientation = 1; } else if (degree > 45 && degree < 135) { mOrientation = 2; } else if (degree > 135 && degree < 225) { mOrientation = 1; } else if (degree > 225 && degree < 315) { mOrientation = 2; } else if (degree > 315 && degree < 360) { mOrientation = 1; } if (mOrientation == 2) {log. I ("OrientationListener ", "landscape "); } else if (mOrientation == 1) {log. I ("OrientationListener ", "portrait "); }}}Copy the code

Special note: Math.atan2(-y, X) calculates the plane Angle (radian value) between the line segment from the origin (0,0) to (X, Y) and the positive X-axis, Float Angle = (float) math.atan2 (-y, X) * OneEightyOverPi; float Angle = (float) math.atan2 (-y, X) * OneEightyOverPi 90 – (int) math. round(Angle) Indicates the Angle of device rotation.

We practice

This section to achieve a simple golf game, practice the use of the acceleration sensor. The game is a multi-player game, the rules of the game are: participants control the movement of the golf ball by shaking the mobile phone, when the golf ball falls into the hole is counted 1 points, otherwise no points, each operation 3 times, the highest score wins. The principle of the game is to obtain the rotation Angle of the equipment according to the acceleration sensor, calculate and update the position of the golf ball in real time, and judge whether the golf ball falls into the hole according to the coincidence of the position of the golf ball and the hole. Points are scored if you fall into the hole; otherwise, no points are scored. The specific implementation of the game is shown in the attachment below.

Link: pan.baidu.com/s/1Kas3kL0f… : 87 nh links: pan.baidu.com/s/1yXNbbI3Q… : 8uaz

extension

Most mobile devices, in addition to the acceleration sensor described above, also have a number of built-in sensors, such as: gravity sensor, rotation vector sensor, screen orientation sensor, temperature sensor, light sensor, pressure sensor, etc. (see sensors for more information). Developers can do a lot of very smart things with these sensors. Such as:

Through the light sensor, automatically adjust the brightness of the screen, protect the user’s eyes through the acceleration sensor, realize the pedometer and motion detection function through the humidity sensor and temperature sensor, calculate the dew point and absolute humidity through GPS, achieve navigation function

Developer.android.com/guide/topic… Developer.android.com/guide/topic… Github.com/googlearchi… V.qq.com/x/page/t050… baike.baidu.com/item/ gravity sensor?…

Accelerometerplay.zip (5.0KB)