修改appium-uiautomator2-server源码解决Android UI自动化不确定弹框问题

1.背景

由于测试应用不确定弹框较多,如果在脚本中判断很耗时间,因此修改appium-uiautomator2-server源码添加监听解决这个问题,目前实现了可配置式的监听,暂时只支持text、resourceId、textContains、content-desc4中查找方式,且只支持简单的点击操作,具体可以根据自己的需求进行扩展。

2.下载appium-uiautomator2-server

根据你所使用的apppium版本下载对应的uiautomator2server源码

3.使用AndroidStudio打开项目

4.添加对弹框的监听

在utils包下新建WatcherUtils类,用于读取配置文档中需要监听的内容

 WatcherUtils代码如下:

package io.appium.uiautomator2.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * 监听工具类,用于读取配置文件中需要监听的内容
 */
public class WatcherUtils {

    /**
     * 读取配置文件
     * @return
     */
    public static List<String> readWatchers(){
        List<String> watcherList = new ArrayList<>();
        String encoding = "GBK";
        File file = new File("/data/local/tmp/watchers.txt");
        if (file.isFile() && file.exists()){
            try {
                InputStream is = new FileInputStream(file);
                InputStreamReader isr = new InputStreamReader(is, encoding);
                BufferedReader br = new BufferedReader(isr);
                String line = "";
                while ((line = br.readLine()) != null){
                    watcherList.add(line);
                }
                br.close();
                isr.close();
                is.close();
            }catch (Exception ex){
                Logger.error("read watchers fail");
            }
        }
        return watcherList;
    }
}

 在AndroidServer类中调用获取配置文件,并添加监听

 代码如下:

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.appium.uiautomator2.server;

import static io.appium.uiautomator2.utils.Device.getUiDevice;

import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiWatcher;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import io.appium.uiautomator2.http.HttpServer;
import io.appium.uiautomator2.utils.Logger;
import io.appium.uiautomator2.utils.WatcherUtils;

public class AndroidServer {
    private final HttpServer webServer;

    public AndroidServer(int port) {
        webServer = new HttpServer(port);
        init();
        List<String> watcherList = WatcherUtils.readWatchers();
        watcherHandler(watcherList);
        Logger.info("AndroidServer created on port " + port);
    }

    private void init() {
        webServer.addHandler(new AppiumServlet());
    }

    public void start() {
        webServer.start();
    }

    public void stop() {
        webServer.stop();
    }

    public int getPort() {
        return webServer.getPort();
    }

    /**
     * 注册监听
     * @param watcherList
     */
    private void watcherHandler(List<String> watcherList){
        //将配置文件中的内容添加到监听
        for (String watcher : watcherList){
            String[] str = watcher.split("#");
            getUiDevice().registerWatcher(str[0], new UiWatcher() {
                @Override
                public boolean checkForCondition() {
                    BySelector selector = findTarget(str[1], str[2]);
                    if (getUiDevice().hasObject(selector)){
                        if (getUiDevice().hasObject(findTarget(str[3], str[4]))){
                            getUiDevice().findObject(findTarget(str[3], str[4])).click();
                        }
                        return true;
                    }
                    return false;
                }
            });
        }
        //设置监听任务
        TimerTask watcherTask = new TimerTask() {
            @Override
            public void run() {
                try {
                    getUiDevice().runWatchers();
                }catch (Exception ex){}
            }
        };
        Timer timer = new Timer("WatcherTimer");
        //每隔5s监听一次
        timer.scheduleAtFixedRate(watcherTask, 1000, 5000);
    }

    private BySelector findTarget(String key, String value){
        BySelector selector = null;
        switch (key){
            case "text":
                selector = By.text(value);
                break;
            case "resourceId":
                selector = By.res(value);
                break;
            case "textContains":
                selector = By.textContains(value);
                break;
            case "content-desc":
                selector = By.desc(value);
                break;
            default:
                break;
        }
        return selector;
    }
}

重新编译,在项目根目录下打开cmd,执行命令

gradlew.bat clean assembleServerDebug assembleServerDebugAndroidTest

编译完成后会在项目\app\build\outputs\apk目录下生成2个apk,将这2个apk替换掉appium\node_modules\appium-uiautomator2-server\apks目录下的apk

5.创建配置文件

创建watchers.txt文件,内容格式如下:

监听名称#触发监听时By#触发监听时的值#触发监听后操作By#触发监听后操作值

 

 例如上面的监听即为当发现页面存在resource-id为close-button-icon时,点击resource-id为close-button-icon的目标

6.测试

将watchers.txt push到手机\data\local\tmp目录下,并见手机中的io.appium.uiautomator2.server、io.appium.uiautomator2.server.test卸载,安装上面编译生成的2个apk后,执行命令启动uiautomator2服务

adb shell am instrument -w io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner

然后进入添加监听的页面,可以看到会自动关掉弹框

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值