在 Android 平台上,使用 Airtest 启动应用时,可能会遇到一个问题:即便应用启动前已经将手机屏幕方向锁定,使用 Airtest
启动应用时,屏幕仍然会自动翻转。这通常是由于设备的重力感应导致的,尤其是在启动过程中,应用的界面可能会依赖重力感应来确定屏幕的方向。为了解决这个问题,我们可以采取两种有效的解决方法,以确保测试过程中屏幕不会自动翻转。
以下将详细介绍这三种方法,并结合源码分析及步骤进行解释。
方法一:在启动应用后禁用自动旋转
在启动应用后,我们可以通过禁用设备的重力感应来防止屏幕自动旋转。通过调用 `adb` 命令禁用设备的自动旋转功能,可以确保屏幕在测试过程中保持固定方向。
步骤:
- 分析 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`,这样也能有效避免应用启动时触发自动旋转的界面。
步骤:
- 分析 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
,可以避免应用在启动过程中进入导致自动旋转的界面。
- 完整示例代码:
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
,这样可以确保应用启动时不会进入导致自动旋转的界面。
方法三:物理解决方案------人为立起手机
如果因设备限制无法使用软件方法,或者测试环境无法更改系统设置,可以采用物理方式将手机固定在直立状态,利用设备的重力感应特性避免屏幕旋转。
步骤:
-
将手机立起: 将手机垂直放置在平稳的桌面或支架上,确保屏幕正对前方。
-
启动应用: 使用
start_app
或其他方法启动应用。在手机处于直立状态时,设备的重力感应通常不会触发屏幕方向切换。
总结
-
方法一:禁用自动旋转。 通过禁用设备的重力感应旋转功能,确保应用启动后,屏幕不会因为设备的重力感应而自动翻转。这种方法适用于任何安卓应用,且实现简单。
-
方法二:指定启动特定的 Activity。 在启动应用时,通过明确指定要启动的
Activity
,避免应用在启动过程中进入可能导致屏幕自动旋转的界面。这种方法适用于应用有多个启动界面时,能够保证启动过程的稳定性,但有小数app不起作用。 -
方法三:立起手机。 快速直接,无需修改系统或代码, 临时测试、环境限制时可尝试。
- 获取当前屏幕活跃package, activity的ADB指令
shell
adb -s 你的设备ID shell dumpsys window | findstr mCurrentFocus
在实际场景中,建议优先选择方法一 或方法二 ,因为它们能在系统层面或逻辑层面稳定解决问题,通常情况下,方法一 禁用自动旋转会更加简单有效,但是会对测试有一定地性能影响。如果你能准确知道需要启动的 Activity,方法二 将更加精确、高效地控制启动过程,避免不必要的屏幕旋转。如果测试环境限制较多,方法三也是一个便捷的替代方案。