监测屏幕旋转的方案,这里简要说一下screenOrientation,OrientationEventListener,SensorEventListener。
方案一
screenOrientation。
在AndroidManifest中,activity配置screenOrientation,比如值为sensor,系统可以自动改变activity的界面方向。在回调onConfigurationChanged()中可以判断当前方向。

<activity android:name=".ui.sensor.ScreenOrientationActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="sensor"/>
优点:简单,系统自动。
缺点:只能监听屏幕方向;系统自动设置方向,当有条件切换时,无法实现需求;无法知道旋转方向。
方案二
OrientationEventListener。
实现OrientationEventListener方法。在适当的位置调用enable()和disable()来开启和关闭监听。
public class OrientationEventActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensor);
initOrientationEvent();
}
OrientationEventListener mOrientationEventListener;
public void initOrientationEvent(){
mOrientationEventListener = new OrientationEventListener(this,
SensorManager.SENSOR_DELAY_NORMAL) {
@Override
public void onOrientationChanged(int orientation) {
if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
return; //手机平放时,检测不到有效的角度
}
//只检测是否有四个角度的改变
if (orientation > 350 || orientation < 10) { //0度
orientation = 0;
} else if (orientation > 80 && orientation < 100) { //90度
orientation = 90;
} else if (orientation > 170 && orientation < 190) { //180度
orientation = 180;
} else if (orientation > 260 && orientation < 280) { //270度
orientation = 270;
} else {
return;
}
}
};
if (mOrientationEventListener.canDetectOrientation()) {
mOrientationEventListener.enable();
} else {
mOrientationEventListener.disable();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mOrientationEventListener !=null){
mOrientationEventListener.disable();
}
}
}
优点:可以判断角度,解决按需设置方向。也能通过判断知道旋转方向。但平放时,无法得到有效的角度。可以通过反射,解决平放时,无法获取角度问题。
public class ScreenOrientationListener extends OrientationEventListener {
private int mOrientation;
private OnOrientationChangedListener mOnOrientationChangedListener;
private Context mContext;
private Field mFieldRotation;
private Object mOLegacy;
public ScreenOrientationListener(Context context) {
super(context);
mContext = context;
}
public void setOnOrientationChangedListener(OnOrientationChangedListener listener) {
this.mOnOrientationChangedListener = listener;
}
public int getOrientation() {
int rotation = -1;
try {
if (null == mFieldRotation) {
SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
Class clazzLegacy = Class.forName("android.hardware.LegacySensorManager");
Constructor constructor = clazzLegacy.getConstructor(SensorManager.class);
constructor.setAccessible(true);
mOLegacy = constructor.newInstance(sensorManager);
mFieldRotation = clazzLegacy.getDeclaredField("sRotation");
mFieldRotation.setAccessible(true);
}
rotation = mFieldRotation.getInt(mOLegacy);
} catch (Exception e) {
LogUtil.e( "getRotation e=" + e.getMessage());
e.printStackTrace();
}
// Log.d(TAG, "getRotation rotation=" + rotation);
int orientation = -1;
switch (rotation) {
case Surface.ROTATION_0:
orientation = 0;
break;
case Surface.ROTATION_90:
orientation = 90;
break;
case Surface.ROTATION_180:
orientation = 180;
break;
case Surface.ROTATION_270:
orientation = 270;
break;
default:
break;
}
// Log.d(TAG, "getRotation orientation=" + orientation);
return orientation;
}
@Override
public void onOrientationChanged(int orientation) {
if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
return; // 手机平放时,检测不到有效的角度
}
orientation = getOrientation();
if (mOrientation != orientation) {
mOrientation = orientation;
if (null != mOnOrientationChangedListener) {
mOnOrientationChangedListener.onOrientationChanged(mOrientation);
LogUtil.d("ScreenOrientationListener onOrientationChanged orientation=" + mOrientation);
}
}
}
public interface OnOrientationChangedListener {
void onOrientationChanged(int orientation);
}
}
方案三
SensorEventListener
package com.ader.demo_unit.ui.sensor;
import android.annotation.TargetApi;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.view.OrientationEventListener;
import android.view.Surface;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.ader.baseapp.base.ui.BaseActivity;
import com.ader.baseapp.base.utils.LogUtil;
import com.ader.demo_unit.R;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* Create by Wang Xiaowu on 2023-02-06
* Describe:
*/
public class SensorActivity extends AppCompatActivity {
SensorManager sm;
SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
// float[] values=event.values;
// String sb="x方向加速度:"+
// values[0]+
// "\nY轴方向加速度:"+
// values[1]+
// "\nZ轴方向加速度:"+
// values[2];
// LogUtil.e(String.format("%s accuracy:%d sensor:%s",sb,event.accuracy,event.sensor.toString()));
//
// /* 判断Sensor的种类 */
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
/* 取得X值资料 */
float x_data = event.values[SensorManager.DATA_X];
if ((x_data > 0 && x_data <= 22.5) || x_data > 337.5) {
LogUtil.e("北方" + String.valueOf(x_data));
} else if (x_data > 22.5 && x_data <= 67.5) {
LogUtil.e("东北方" + String.valueOf(x_data));
} else if (x_data > 67.5 && x_data <= 112.5) {
LogUtil.e("东方" + String.valueOf(x_data));
} else if (x_data > 112.5 && x_data <= 157.5) {
LogUtil.e("东南方" + String.valueOf(x_data));
} else if (x_data > 157.5 && x_data <= 202.5) {
LogUtil.e("南方" + String.valueOf(x_data));
} else if (x_data > 202.5 && x_data <= 247.5) {
LogUtil.e("西南方" + String.valueOf(x_data));
} else if (x_data > 247.5 && x_data <= 292.5) {
LogUtil.e("西方" + String.valueOf(x_data));
} else if (x_data > 292.5 && x_data <= 337.5) {
LogUtil.e("西北方" + String.valueOf(x_data));
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
LogUtil.e(String.format("onAccuracyChanged accuracy:%d sensor:%s",accuracy,sensor.toString()));
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensor);
//1.获取系统的传感器管理服务
sm = (SensorManager)getSystemService(SENSOR_SERVICE);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onResume() {
super.onResume();
//2.
// 为系统的加速度传感器注册监听事件
// sm.registerListener(mSensorEventListener,
// sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
// SensorManager.SENSOR_DELAY_GAME);
// //方向传感器
sm.registerListener(mSensorEventListener,
sm.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_FASTEST);
//* Sensor.TYPE_ORIENTATION:方向传感器。
//
//* Sensor.TYPE_GYROSCOPE:陀螺仪传感器。
//
//* Sensor.TYPE_MAGNETIC_FIELD:磁场传感器。
//
//* Sensor.TYPE_GRAVITY:重力传感器。
//
//* Sensor.TYPE_LINEAR_ACCELERATION:线性加速度传感器。
//
//* Sensor.TYPE_AMBIENT_TEMPERATURE:温度传感器。
//
//* Sensor.TYPE_LIGHT:光传感器。
//
//* Sensor.TYPE_PRESSURE:压力传感器。
}
@Override
protected void onPause() {
super.onPause();
//取消注册
sm.unregisterListener(mSensorEventListener);
}
}
可以获取位置方向,但获取屏幕方向有点困难。已经被废弃。官方推荐使用 SensorManager.getOrientation() 替代。