解决 Airtest 启动 APP 自动翻转屏幕问题的三种方法

在 Android 平台上,使用 Airtest 启动应用时,可能会遇到一个问题:即便应用启动前已经将手机屏幕方向锁定,使用 Airtest 启动应用时,屏幕仍然会自动翻转。这通常是由于设备的重力感应导致的,尤其是在启动过程中,应用的界面可能会依赖重力感应来确定屏幕的方向。为了解决这个问题,我们可以采取两种有效的解决方法,以确保测试过程中屏幕不会自动翻转。

以下将详细介绍这三种方法,并结合源码分析及步骤进行解释。

方法一:在启动应用后禁用自动旋转

在启动应用后,我们可以通过禁用设备的重力感应来防止屏幕自动旋转。通过调用 `adb` 命令禁用设备的自动旋转功能,可以确保屏幕在测试过程中保持固定方向。

步骤:
  1. 分析 start_app函数源码: start_app 是 Airtest 中用于启动应用的主要函数,源码如下:
python 复制代码
@logwrap
def start_app(package, activity=None):
    """
    Start the target application on device

    :param package: name of the package to be started, e.g. "com.netease.my"
    :param activity: the activity to start, default is None which means the main activity
    :return: None
    :platforms: Android, iOS
    :Example:
        >>> start_app("com.netease.cloudmusic")
        >>> start_app("com.apple.mobilesafari")  # on iOS
    """
    G.DEVICE.start_app(package, activity)

该函数会调用 G.DEVICE.start_app 来启动应用,package 是应用的包名,activity 是应用的启动页面(默认为 None,表示启动默认的主界面)。 2. 分析 G.DEVICE.start_app 源码: start_app 函数会通过 adb shell 执行命令来启动应用,具体如下:

python 复制代码
    def start_app(self, package, activity=None):
        """
        Perform `adb shell monkey` commands to start the application, if `activity` argument is `None`, then
        `adb shell am start` command is used.

        Args:
            package: package name
            activity: activity name

        Returns:
            None

        """
        if not activity:
            try:
                ret = self.shell(['monkey', '-p', package, '-c', 'android.intent.category.LAUNCHER', '1'])
            except AdbShellError as e:
                raise AirtestError("Starting App: %s Failed! No activities found to run." % package)
            if "No activities found to run" in ret:
                raise AirtestError("Starting App: %s Failed! No activities found to run." % package)
        else:
            self.shell(['am', 'start', '-n', '%s/%s.%s' % (package, package, activity)])

如果 activity 参数为空,使用 adb shell monkey 启动应用。如果提供了 activity,则使用 adb shell am start 启动特定的 Activity。 3. 禁用自动旋转:通过 adb 命令禁用设备的自动旋转功能:

plain 复制代码
dev.shell("settings put system accelerometer_rotation 0")

. 4. 完整示例代码:

python 复制代码
deviceID = "你的设备id"
app = "com.xxxx"
activity = "com.ss.android.xxxx"
dev = connect_device(f"Android://127.0.0.1:5037/{deviceID}")

# 启动应用
start_app(app)
# 禁止自动旋转屏幕
dev.shell("settings put system accelerometer_rotation 0")

在这段代码中,我们先启动应用 app,然后通过 dev.shell("settings put system accelerometer_rotation 0") 禁用了设备的加速度感应旋转功能。这样,在测试过程中,屏幕方向将会自动调整过来。

方法二:指定启动特定的 Activity

我们可以在启动应用时,明确指定启动的 `Activity`,这样也能有效避免应用启动时触发自动旋转的界面。

步骤:
  1. 分析 start_app函数源码:如果提供了 `activity` 参数,`start_app` 会使用 `adb shell am start` 命令启动特定的 Activity:
python 复制代码
    def start_app(self, package, activity=None):
        """
        Perform `adb shell monkey` commands to start the application, if `activity` argument is `None`, then
        `adb shell am start` command is used.

        Args:
            package: package name
            activity: activity name

        Returns:
            None

        """
        if not activity:
            try:
                ret = self.shell(['monkey', '-p', package, '-c', 'android.intent.category.LAUNCHER', '1'])
            except AdbShellError as e:
                raise AirtestError("Starting App: %s Failed! No activities found to run." % package)
            if "No activities found to run" in ret:
                raise AirtestError("Starting App: %s Failed! No activities found to run." % package)
        else:
            self.shell(['am', 'start', '-n', '%s/%s.%s' % (package, package, activity)])

注意如上源代码通过 self.shell(['am', 'start', '-n', '%s/%s.%s' % (package, package, activity)]) 来启动app其实是有问题的,我们可以参考github.com/mzlogin/awe...

调整为self.shell(['am', 'start', '-n', '%s/%s' % (package, activity)]),如下是修改后的源码

python 复制代码
def start_app(self, package, activity=None):
    """
        Perform `adb shell monkey` commands to start the application, if `activity` argument is `None`, then
        `adb shell am start` command is used.

        Args:
            package: package name
            activity: activity name

        Returns:
            None

        """
    if not activity:
        try:
            ret = self.shell(['monkey', '-p', package, '-c', 'android.intent.category.LAUNCHER', '1'])
        except AdbShellError as e:
            raise AirtestError("Starting App: %s Failed! No activities found to run." % package)
            if "No activities found to run" in ret:
                raise AirtestError("Starting App: %s Failed! No activities found to run." % package)
    else:
        # 注释原来错误的启动命令
        # self.shell(['am', 'start', '-n', '%s/%s.%s' % (package, package, activity)])
        # 更改为正确的启动命令
        self.shell(['am', 'start', '-n', '%s/%s' % (package, activity)])

在此方法中,我们通过传入 activity 参数,明确指定要启动的 SplashActivity,这样可以确保应用启动时不会进入导致自动旋转的界面。 2. 传入 activity 参数: 通过明确指定要启动的 Activity,可以避免应用在启动过程中进入导致自动旋转的界面。

  1. 完整示例代码:
python 复制代码
deviceID = "你的设备id"
app = "com.xxxx"
activity = "com.ss.android.xxxx"
dev = connect_device(f"Android://127.0.0.1:5037/{deviceID}")

# 使用方式二,明确指定 Activity 启动
start_app(youtube_app, activity)

在此方法中,我们通过传入 activity 参数,明确指定要启动的 SplashActivity,这样可以确保应用启动时不会进入导致自动旋转的界面。

方法三:物理解决方案------人为立起手机

如果因设备限制无法使用软件方法,或者测试环境无法更改系统设置,可以采用物理方式将手机固定在直立状态,利用设备的重力感应特性避免屏幕旋转。

步骤:
  1. 将手机立起: 将手机垂直放置在平稳的桌面或支架上,确保屏幕正对前方。

  2. 启动应用: 使用 start_app 或其他方法启动应用。在手机处于直立状态时,设备的重力感应通常不会触发屏幕方向切换。

总结

  1. 方法一:禁用自动旋转。 通过禁用设备的重力感应旋转功能,确保应用启动后,屏幕不会因为设备的重力感应而自动翻转。这种方法适用于任何安卓应用,且实现简单。

  2. 方法二:指定启动特定的 Activity。 在启动应用时,通过明确指定要启动的 Activity,避免应用在启动过程中进入可能导致屏幕自动旋转的界面。这种方法适用于应用有多个启动界面时,能够保证启动过程的稳定性,但有小数app不起作用。

  3. 方法三:立起手机。 快速直接,无需修改系统或代码, 临时测试、环境限制时可尝试。

  • 获取当前屏幕活跃package, activity的ADB指令
shell 复制代码
adb -s 你的设备ID shell dumpsys window | findstr mCurrentFocus

在实际场景中,建议优先选择方法一方法二 ,因为它们能在系统层面或逻辑层面稳定解决问题,通常情况下,方法一 禁用自动旋转会更加简单有效,但是会对测试有一定地性能影响。如果你能准确知道需要启动的 Activity,方法二 将更加精确、高效地控制启动过程,避免不必要的屏幕旋转。如果测试环境限制较多,方法三也是一个便捷的替代方案。

相关推荐
程序员爱钓鱼1 小时前
Go语言实战案例-判断一个数是否为质数
后端·google·go
程序员爱钓鱼1 小时前
Go语言实战案例-读取本地文本文件内容
后端·google·go
都叫我大帅哥1 小时前
Python的Optional:让你的代码优雅处理“空值”危机
python
曾几何时`3 小时前
基于python和neo4j构建知识图谱医药问答系统
python·知识图谱·neo4j
写写闲篇儿5 小时前
Python+MongoDB高效开发组合
linux·python·mongodb
杭州杭州杭州6 小时前
Python笔记
开发语言·笔记·python
路人蛃8 小时前
通过国内扣子(Coze)搭建智能体并接入discord机器人
人工智能·python·ubuntu·ai·aigc·个人开发
qiqiqi(^_×)8 小时前
卡在“pycharm正在创建帮助程序目录”
ide·python·pycharm
Ching·9 小时前
esp32使用ESP-IDF在Linux下的升级步骤,和遇到的坑Traceback (most recent call last):,及解决
linux·python·esp32·esp_idf升级
mCell9 小时前
Go 并发编程基础:从 Goroutine 到 Worker Pool 实践
后端·性能优化·go