Android 如何全局检测屏幕旋转的变化? 问题:
在Android服务中,我想检测屏幕旋转的变化。我所说的旋转,不仅仅是指肖像和风景;我指的是屏幕旋转的任何变化。此类变更的示例包括:Android 如何全局检测屏幕旋转的变化? 问题:,android,screen-orientation,screen-rotation,orientation-changes,Android,Screen Orientation,Screen Rotation,Orientation Changes,在Android服务中,我想检测屏幕旋转的变化。我所说的旋转,不仅仅是指肖像和风景;我指的是屏幕旋转的任何变化。此类变更的示例包括: 肖像画 倒像 景观 反向风景 请注意,此问题与设备方向的更改无关。这只是关于屏幕方向/旋转 我试过的 通过ACTION\u Configuration\u CHANGED监听配置的更改。这只包括纵向和横向之间的变化,因此180°的变化不会触发这种变化 我为什么要这么做 我正在开发一个定制的屏幕方向管理应用程序。批准的答案可以使用,但如果您想要更高的检测分辨
- 肖像画
- 倒像
- 景观
- 反向风景
- 通过
监听ACTION\u Configuration\u CHANGED
配置的更改。这只包括纵向和横向之间的变化,因此180°的变化不会触发这种变化
我正在开发一个定制的屏幕方向管理应用程序。批准的答案可以使用,但如果您想要更高的检测分辨率(或支持API 3),请尝试使用
OrientationEventListener
,它可以以度为单位报告手机的方向
mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
OrientationEventListener orientationEventListener = new OrientationEventListener(this,
SensorManager.SENSOR_DELAY_NORMAL) {
@Override
public void onOrientationChanged(int orientation) {
Display display = mWindowManager.getDefaultDisplay();
int rotation = display.getRotation();
if(rotation != mLastRotation){
//rotation changed
if (rotation == Surface.ROTATION_90){} // check rotations here
if (rotation == Surface.ROTATION_270){} //
}
mLastRotation = rotation;
}
};
if (orientationEventListener.canDetectOrientation()) {
orientationEventListener.enable();
}
另一种方法(而不是上述学院提供的方法)是在onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
if (rotation == Surface.ROTATION_180) { // reverse portrait
setContentView(R.layout.main_reverse_portrait);
} else { // for all other orientations
setContentView(R.layout.main);
}
...
}
使用隐藏的API
您可以使用一个名为。从我的测试来看,每次屏幕旋转发生变化时都会调用回调。回调似乎也给出了当前的屏幕旋转
作为一个隐藏的API,您不能直接调用它。如何使用隐藏的API是它自己的主题。当然,从可维护性的角度来看,这可能不如普通API那么可靠
而且,在您以前调用的同一线程中没有调用。一旦进入,您可能希望将一些工作委派给不同的线程,例如UI线程
兼容性
在API 14-28中测试和工作
例子
有一种方法可以让它工作:
试试看{
Class serviceManager=Class.forName(“android.os.serviceManager”);
IBinder serviceBinder=(IBinder)serviceManager.getMethod(“getService”,String.class).invoke(serviceManager,window”);
Class stub=Class.forName(“android.view.IWindowManager$stub”);
对象windowManagerService=stub.getMethod(“asInterface”,IBinder.class).invoke(stub,serviceBinder);
方法观察旋转;
如果(Build.VERSION.SDK_INT>=26)
watchRotation=windowManagerService.getClass().getMethod(“watchRotation”,IRotationWatcher.class,int.class);
其他的
watchRotation=windowManagerService.getClass().getMethod(“watchRotation”,IRotationWatcher.class);
//这种方法似乎已经在Android 4.3中引入,所以不要期望总是找到它
方法RemoveTotationWatcher=null;
试一试{
RemoveOtationWatcher=windowManagerService.getClass().getMethod(“RemoveOtationWatcher”,IRotationWatcher.class);
}
捕获(忽略NoSuchMethodException){}
IRotationWatcher.Stub screenRotationChanged=新建IRotationWatcher.Stub(){
@凌驾
公共void onRotationChanged(int-rotation)引发远程异常{
//你想在这里干什么就干什么
//警告:这不是在调用watchRotation时所在的同一线程中调用的
}
};
//开始监视更改
如果(Build.VERSION.SDK_INT>=26)
watchRotation.invoke(windowManagerService,screenRotationChanged,Display.DEFAULT_Display);
其他的
watchRotation.invoke(windowManagerService,screenRotationChanged);
//完成后停止监视更改
如果(RemoveOtationWatcher!=null){
RemoveOtationWatcher.invoke(windowManagerService,screenRotationChanged);
}catch(ClassNotFoundException | ClassCastException | InvocationTargetException | NoSuchMethodException | IllegaAccessException e){
抛出新的运行时异常(e);
}
是的;我已经看过了
方向ventlistener
,但它监控设备的方向。正如我在问题中所说,“这个问题不是关于设备方向的更改”。这不包括由于切换应用程序、切换自动旋转或更改用户旋转而导致的方向更改等情况。这不会告诉我屏幕方向何时更改;它只告诉我该时间点的当前状态。onRotationChanged
从未为我调用
try {
Class<?> serviceManager = Class.forName("android.os.ServiceManager");
IBinder serviceBinder = (IBinder)serviceManager.getMethod("getService", String.class).invoke(serviceManager, "window");
Class<?> stub = Class.forName("android.view.IWindowManager$Stub");
Object windowManagerService = stub.getMethod("asInterface", IBinder.class).invoke(stub, serviceBinder);
Method watchRotation;
if (Build.VERSION.SDK_INT >= 26)
watchRotation = windowManagerService.getClass().getMethod("watchRotation", IRotationWatcher.class, int.class);
else
watchRotation = windowManagerService.getClass().getMethod("watchRotation", IRotationWatcher.class);
//This method seems to have been introduced in Android 4.3, so don't expect to always find it
Method removeRotationWatcher = null;
try {
removeRotationWatcher = windowManagerService.getClass().getMethod("removeRotationWatcher", IRotationWatcher.class);
}
catch (NoSuchMethodException ignored) {}
IRotationWatcher.Stub screenRotationChanged = new IRotationWatcher.Stub() {
@Override
public void onRotationChanged(int rotation) throws RemoteException {
//Do what you want here
//WARNING: This isn't called in the same thread you were in when you called watchRotation
}
};
//Start monitoring for changes
if (Build.VERSION.SDK_INT >= 26)
watchRotation.invoke(windowManagerService, screenRotationChanged, Display.DEFAULT_DISPLAY);
else
watchRotation.invoke(windowManagerService, screenRotationChanged);
//Stop monitoring for changes when you're done
if (removeRotationWatcher != null) {
removeRotationWatcher.invoke(windowManagerService, screenRotationChanged);
} catch (ClassNotFoundException | ClassCastException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
throw new RuntimeException(e);
}