IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 自动化交互实践 -> 正文阅读

[移动开发]Android 自动化交互实践

李涛

2015年3月加入去哪儿网,客户端开发工程师,曾经担任酒店业务和自助入离机项目开发。现负责国际酒店抓取系统开发与维护。


Android 自动化交互可以代替人工完成重复性的工作,包括通过自动操作 App 进行黑盒测试和第三方 App 的自动运行。常见的自动化交互包含启动 App、view 的点击、拖拽和文本输入等。随着 App 安防能力的提升,要想实现完整流程的自动化交互变的越来越困难,本文主要探讨目前常见的自动化交互方案以及不同方案的优劣和应用场景。


1. 传统执行脚本方案

ADB 是 Google 提供的能够和 Android 设备进行交互的命令行工具,我们可以编写脚本按照事先设计好的顺序,一个一个执行各个事件。ADB 执行操作需要事先获取界面元素的坐标(获取坐标方法可以利用 uiautomator 或者 dump xml 的方法,这里不是讨论的重点),然后把坐标传入作为命令行参数。

adb shell input tap 100 500

上面命令是模拟点击屏幕坐标为(100, 500)处的控件。

adb shell input swipe 100 500 200 600

上面命令是模拟手指在屏幕上向右下方滑动的一个操作。

adb shell input keyevent "KEYCODE_BACK"

上面命令模拟返回按键的点击。
一次完整的自动化交互流程可由上面一系列命令顺序执行。

ADB 脚本方式的优点

实现简单,只需要获取目标元素的坐标等简单信息即可完成相关操作

可以实现对 webview 的自动化交互

ADB 脚本方式的缺点

灵活度不够,依赖于写死的坐标,App 界面变更引起的 view 位置变换会让脚本中相关命令无法执行,需要重新分析页面坐标

需要建立 ADB 链接或套接字链接,交互过程中网络状况的变化会影响自动化交互效果

ADB 脚本方式应用场景

交互简单、迭代频率低,安防级别比较低的 App

webview 页面,flutter 开发的 App


2. Android 原生方法实现自动化交互

我们可以借助各种插件化框架来控制 App 页面的界面元素,其中一种思路就是在插件中借助 ActivityLifecycleCallbacks 来监听各个 activity 的生命周期。

public class MyApplication extends Application {
    private static final String TAG = "MyApplication";
    //声明一个监听Activity们生命周期的接口
    private ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
        /**
         * application下的每个Activity声明周期改变时,都会触发以下的函数。
         */
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            //如何区别参数中activity代表你写的哪个activity。
            if (activity.getClass() == MainActivity.class)
                Log.d(TAG, "MainActivityCreated.");
            else if(activity.getClass()== SecondActivity.class)
                Log.d(TAG, "SecondActivityCreated.");
        }

        @Override
        public void onActivityStarted(Activity activity) {
            Log.d(TAG, "onActivityStarted.");
        }

        @Override
        public void onActivityResumed(Activity activity) {
            Log.d(TAG, "onActivityResumed.");
        }

        @Override
        public void onActivityPaused(Activity activity) {
            Log.d(TAG, "onActivityPaused.");
        }

        @Override
        public void onActivityStopped(Activity activity) {
            Log.d(TAG, "onActivityStopped.");
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
            Log.d(TAG, "onActivityDestroyed.");
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        //注册自己的Activity的生命周期回调接口。![Alt text](./WechatIMG59.png)

        registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
    }

    @Override
    public void onTerminate() {
        //注销这个接口。
        unregisterActivityLifecycleCallbacks(activityLifecycleCallbacks);
        super.onTerminate();
    }
}

监听到 activity 的活动后,可以借助 uiautomator 分析 activity 界面元素的 viewId 以及属性,不同情况的界面 view 可以采用不同的自动化方法。

2.1 简单 view 的处理方式

如下图:
在这里插入图片描述
像这类 view,可以直接获取到 resource id ,并且确认可点击属性为 true,操作方式比较简单, 可以在监听到的 activity 生命周期中执行如下操作:

int fl_btn = activity.getResources().getIdentifier("dashboard_title",         "id", "com.android.settings");
View v =  activity.findViewById(fl_btn);

v.performClick();

2.2 隐藏属性的 view 的处理方式

在一些对 view 的属性进行隐藏,特别是利用 React Native 等混合开发的页面,上面的方法不再生效,如下图所示的 view:
在这里插入图片描述
如图,选中的 viewgroup 及其子 view 的 clickable 属性均为 false,并且无法获取到 view 的 resource id,这时候可以利用图中 dump 出的布局信息,借助 Xpath 元素定位工具来获取到界面的 view,由于这些 view 的点击属性为 false,因此通过调用 performClick 来实现点击的方法已经无效,此时考虑在 click 更底层的与触摸事件传递相关的比较重要的类:MotionEvent, MotionEvent 可以仿真几乎所有的交互事件,包括点击,滑动,双指操作等。以单击为例:

    private void simulateClick(View view, float x, float y) {
        long time = SystemClock.uptimeMillis();//必须是 SystemClock.uptimeMillis()。

        MotionEvent downEvent = MotionEvent.obtain(time, time, MotionEvent.ACTION_DOWN, x, y, 0);

        time += 500;

        MotionEvent upEvent = MotionEvent.obtain(time, time, MotionEvent.ACTION_UP, x, y, 0);

        view.onTouchEvent(downEvent);
        view.onTouchEvent(upEvent);
    }

如果是滑动操作,可以在起始位置中间添加若干 ACTION_MOVE 类型的 MotionEvent. 综上所述,借助系统原生方法时间交互自动化的优缺点大致如下:

借助插件框架实现自动化交互的优点

  • 可维护性强,因为可以直接获取到界面的 view 对象,因此即使页面布局发生变化,只要 view 还存在,就不需要对代码进行修改

  • 仿真效果更好,比脚本方式更接近真人操作

借助插件框架实现自动化交互的不足

  • 对 webview、flutter 框架 App 支持不好

应用场景

  • 版本迭代频繁的 App

  • 非 flutter 框架开发的 App

上面分析了两种常用的模拟真实用户进行自动化操作的方法,脚本方式和调用原生方法的方式,这两种方法基本上可以完成简单的交互流程,在此基础上,我们还可以去深究一些更深层次的交互实现,比如自动化过各种验证等,也可以基于这两种方法来完成。


在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-13 12:13:24  更:2021-08-13 12:16:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 1:05:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码