Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何全局检测屏幕旋转的变化? 问题:_Android_Screen Orientation_Screen Rotation_Orientation Changes - Fatal编程技术网

Android 如何全局检测屏幕旋转的变化? 问题:

Android 如何全局检测屏幕旋转的变化? 问题:,android,screen-orientation,screen-rotation,orientation-changes,Android,Screen Orientation,Screen Rotation,Orientation Changes,在Android服务中,我想检测屏幕旋转的变化。我所说的旋转,不仅仅是指肖像和风景;我指的是屏幕旋转的任何变化。此类变更的示例包括: 肖像画 倒像 景观 反向风景 请注意,此问题与设备方向的更改无关。这只是关于屏幕方向/旋转 我试过的 通过ACTION\u Configuration\u CHANGED监听配置的更改。这只包括纵向和横向之间的变化,因此180°的变化不会触发这种变化 我为什么要这么做 我正在开发一个定制的屏幕方向管理应用程序。批准的答案可以使用,但如果您想要更高的检测分辨

在Android服务中,我想检测屏幕旋转的变化。我所说的旋转,不仅仅是指肖像和风景;我指的是屏幕旋转的任何变化。此类变更的示例包括:

  • 肖像画
  • 倒像
  • 景观
  • 反向风景
请注意,此问题与设备方向的更改无关。这只是关于屏幕方向/旋转

我试过的
  • 通过
    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);
    }