Bootstrap是一个jar包,在启动appium脚本的时候回被push到android 的/data/Local/Tmp目录下,再通过PC端命令执行该Case

//UiAutomatorTestCase 是Android自带的测试用例集public class Bootstrap extends UiAutomatorTestCase {  public void testRunServer() {     ...    SocketServer server;    try {    //构造方法中创建一个Socket连接监听4724端口      server = new SocketServer(4724);      server.listenForever(disableAndroidWatchers, acceptSSLCerts);    } catch (final SocketServerException e) {      Logger.error(e.getError());      System.exit(1);    }  }} public SocketServer(final int port) throws SocketServerException {    keepListening = true;    //初始化Android命令集执行器,其中有一个map存放了appium所有能够使用的操作命令    executor = new AndroidCommandExecutor();    try {      server = new ServerSocket(port);      Logger.debug("Socket opened on port " + port);    } catch (final IOException e) {      throw new SocketServerException(          "Could not start socket server listening on " + port);    }  }

当pc端发送指令执行该测试用例时会先创建个Socket服务端连接,并调用listenForever()方法,监听4724端口,该端口与appium通信。。

 public void listenForever(boolean disableAndroidWatchers, boolean acceptSSLCerts) throws SocketServerException {    //读取push过来的json文件并转成JsonObject    UpdateStrings.loadStringsJson();    if (disableAndroidWatchers) {      Logger.debug("Skipped registering crash watchers.");    } else {      //设置ANR跟Crash监听器      dismissCrashAlerts();     //设置Dialog监听器,并保持心跳检查      final TimerTask updateWatchers = new TimerTask() {        @Override        public void run() {          try {            watchers.check();          } catch (final Exception e) {          }        }      };      timer.scheduleAtFixedRate(updateWatchers, 100, 100);    }    ...    try {      //等待客户端接入      client = server.accept();      in = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));      out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));      while (keepListening) {      //处理客户端数据        handleClientData();      }      in.close();      out.close();      client.close();      Logger.debug("Closed client connection");    } catch (final IOException e) {      throw new SocketServerException("Error when client was trying to connect");    }  }

当appium客户端数据发送过来的时候回转移到handleClientData()方法

 private void handleClientData() throws SocketServerException {    try {    //清空StringBuffer      input.setLength(0); // clear      String res;      int a;      // (char) -1 is not equal to -1.      // ready is checked to ensure the read call doesn't block.      while ((a = in.read()) != -1 && in.ready()) {        input.append((char) a);      }      String inputString = input.toString();           try {      //将客户端数据封装成命令        AndroidCommand cmd = getCommand(inputString);        //执行命令        res = runCommand(cmd);      } catch (final CommandTypeException e) {      //封装执行结果        res = new AndroidCommandResult(WDStatus.UNKNOWN_ERROR, e.getMessage())            .toString();      } catch (final JSONException e) {        res = new AndroidCommandResult(WDStatus.UNKNOWN_ERROR,            "Error running and parsing command").toString();      }      out.write(res);      out.flush();    } catch (final IOException e) {      throw new SocketServerException("Error processing data to/from socket ("          + e.toString() + ")");    }  }

当接收到客户端的数据时通过命令模式,将数据封装成AndroidCommand命令,再交给命令的响应者UiDevice 或UiObject来执行

private String runCommand(final AndroidCommand cmd) {    AndroidCommandResult res;    // 结束    if (cmd.commandType() == AndroidCommandType.SHUTDOWN) {      keepListening = false;      res = new AndroidCommandResult(WDStatus.SUCCESS, "OK, shutting down");    } else if (cmd.commandType() == AndroidCommandType.ACTION) {      try {      //执行命令        res = executor.execute(cmd);      }     .....    return res.toString();  } public AndroidCommandResult execute(final AndroidCommand command) {    try {      //获取命令的action,判断客户端传来的动作类型是否是map中支持的动作      //如果是的则由相应的动作类执行,否则异常处理      if (map.containsKey(command.action())) {        return map.get(command.action()).execute(command);      }      .............  }

封装好命令后就开始调用runCommand()执行命令.这里有个map是静态代码块初始化的,定义了appium所有可以跟UiAutomator交互的动作例如

 static {    map.put("waitForIdle", new WaitForIdle());    map.put("clear", new Clear());}

Clear类就是clear动作的执行者。我们看一个简单的waitFordle命令执行

public class WaitForIdle extends CommandHandler {  @Override  public AndroidCommandResult execute(final AndroidCommand command)      throws JSONException {    //获取客户端的参数    final Hashtable params = command.params();    long timeout = 10;    if (params.containsKey("timeout")) {      timeout = (Integer) params.get("timeout");    }    //具体的执行者执行,并返回结果    UiDevice d = UiDevice.getInstance();    d.waitForIdle(timeout);    return getSuccessResult(true);  }}

这样我们就分析完Appium在android执行的原理了。
总结:appium是通过自身实现一个android UiAutomator框架的case,这个case创建了一个网络通信,通过appium客户端的指令来实现UI操作,并将操作结果返回给Appium客户端


QQ图片20180129192831.jpg

更多相关文章

  1. Android模拟器无法上网解决方案
  2. 2011.09.23——— android sample之Notepad(context menu)
  3. android listview onItemClick不执行
  4. Android(安卓)SDK中的必会工具-android
  5. Ubuntu下编译AOSP步骤
  6. Android中bindService的使用及Service生命周期
  7. 用CSS3生成的一个漂亮的android客户端页面
  8. Android命令行启动程序-am命令的使用-纠正网上大部分资料的错误
  9. Android客户端向服务器端发送数据的流程(1)

随机推荐

  1. Android引路蜂地图开发示例:第一个地图应
  2. android手机图片查看
  3. Android(安卓)- Looper.prepare()和Loope
  4. runONUIThread 分析与使用
  5. Android NDK之JNI使用例子
  6. Android之android:theme设置在Applicatio
  7. 深入了解android平台的jni(二)
  8. Android弹出软键盘布局是否上移问题
  9. Android AlarmManager的取消
  10. Mediaplayer中通过create函数获取资源时P