Android强制设置所有应用显示方向,忽略应用本身的设置

在ROM定制系统开发过程中经常会遇到需要改变第三方应用显示方向的需求,比如抖音这种手机APP都是强制竖屏的,不会跟随屏幕旋转。但在一些平板方案开发中需要能横屏显示,或者需要跟随屏幕旋转方向动态切换横竖屏显示。这时就需要在系统层面去处理了。

先梳理一下屏幕旋转时系统处理的大致流程:

Android 屏幕旋转处理是一个涉及硬件、系统服务、应用层的复杂过程。以下是屏幕旋转处理流程的概述:

  1. 硬件层 (G-sensor):设备中的加速度传感器(G-sensor)检测到物理方向和加速度变化,判断设备的旋转方向 。

  2. 系统服务 (Sensor Service):Sensor Service 管理和提供传感器数据。当 G-sensor 检测到方向变化时,数据会传递到 Sensor Service 。

  3. 方向监听器 (Orientation Listener):应用可以注册方向监听器来监听设备的方向变化,通过 Sensor Service 获取传感器数据,并计算设备的方向 。

  4. 窗口管理器 (Window Manager):窗口管理器负责处理屏幕旋转,调整显示方向以确保用户界面正确显示 。

  5. 配置改变 (Configuration Change) :屏幕旋转会触发应用的配置改变事件,导致活动(Activity)重新创建,并触发 onConfigurationChanged 回调 。

  6. Activity 生命周期处理 :屏幕旋转导致配置改变时,活动会经历生命周期的重新创建阶段,如 onDestroy、onCreate、onStart 和 onResume 。

  7. 重新绘制界面:屏幕旋转后,系统请求重新绘制界面以适应新的方向,应用的布局会根据新的配置进行重新计算和绘制 。

  8. 处理保存的状态 :应用需要处理保存和恢复状态,以确保用户数据的连续性,Android 提供了 onSaveInstanceState 和 onRestoreInstanceState 方法 。

在代码层面,可以通过 setRequestedOrientation 方法设置屏幕方向,此方法等同于在 AndroidManifest.xml 中设置 android:screenOrientation 属性 。设置之后,可以通过 onConfigurationChanged 方法来响应方向变化 。

另外,系统设置中的自动旋转开关会影响应用的屏幕旋转行为。当自动旋转关闭时,无论设备如何旋转,应用界面都不会旋转,除非应用通过代码强制旋转 。用户可以通过下拉通知栏快速切换自动旋转的开启和关闭 。

我们需要做的是在上述第4步中处理,具体修改如下:

frameworks\base\services\core\java\com\android\server\wm\DisplayRotation.java中的

rotationForOrientation(@ScreenOrientation int orientation,@Surface.Rotation int lastRotation)方法就是处理应用中的显示方向设置的,第一个参数orientation就是应用设置的方向,在此方法中进行拦截重写即可。代码如下:

复制代码
    /**
     * Given an orientation constant, returns the appropriate surface rotation, taking into account
     * sensors, docking mode, rotation lock, and other factors.
     *
     * @param orientation  An orientation constant, such as
     *                     {@link ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
     * @param lastRotation The most recently used rotation.
     * @return The surface rotation to use.
     */
    @VisibleForTesting
    @Surface.Rotation
    int rotationForOrientation(@ScreenOrientation int orientation,
            @Surface.Rotation int lastRotation) {
        ProtoLog.v(WM_DEBUG_ORIENTATION,
                "rotationForOrientation(orient=%s (%d), last=%s (%d)); user=%s (%d) %s",
                ActivityInfo.screenOrientationToString(orientation), orientation,
                Surface.rotationToString(lastRotation), lastRotation,
                Surface.rotationToString(mUserRotation), mUserRotation,
                mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
                        ? "USER_ROTATION_LOCKED" : "");

        // 重置orientation,强制所有应用跟随屏幕旋转,也可以设置成强制横屏或竖屏固定
        orientation = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
        //在系统原有的检查是否设置了固定屏幕之前设置,否则系统设置中的开关就无效了
        if (isFixedToUserRotation()) { 
            return mUserRotation;
        }

        int sensorRotation = mOrientationListener != null
                ? mOrientationListener.getProposedRotation() // may be -1
                : -1;
        if (sensorRotation < 0) {
            sensorRotation = lastRotation;
        }
        ...
}

这里顺带记录一下我开发过程中遇到的另一个问题,有些设备屏幕旋转后不会回调

复制代码
onConfigurationChanged()方法,而是重新走onCreate()流程了,Manifest中开始是这样设置的:
复制代码
android:configChanges="orientation|screenSize",此设置大部分设置都可以正常回调,后来查询得知加上screenLayout配置就都可以了,如下:
复制代码
android:configChanges="orientation|screenSize|screenLayout"
相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui