zoukankan      html  css  js  c++  java
  • bootstrap之Orientation

    Orientation


    调整屏幕方向的操作。


    package io.appium.android.bootstrap.handler;
    
    import android.os.RemoteException;
    import com.android.uiautomator.core.UiDevice;
    import io.appium.android.bootstrap.*;
    import org.json.JSONException;
    
    import java.util.Hashtable;
    
    /**
     * This handler is used to get or set the orientation of the device.
     * 
     */
    public class Orientation extends CommandHandler {
    
      /*
       * @param command The {@link AndroidCommand} used for this handler.
       * 
       * @return {@link AndroidCommandResult}
       * 
       * @throws JSONException
       * 
       * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android.
       * bootstrap.AndroidCommand)
       */
      @Override
      public AndroidCommandResult execute(final AndroidCommand command)
          throws JSONException {
    
        final Hashtable<String, Object> params = command.params();
        if (params.containsKey("orientation")) {
          // Set the rotation
    
          final String orientation = (String) params.get("orientation");
          try {
            return handleRotation(orientation);
          } catch (final Exception e) {
            return getErrorResult("Unable to rotate screen: " + e.getMessage());
          }
        } else {
          // Get the rotation
          return getRotation();
        }
    
      }
    
      /**
       * Returns the current rotation
       * 
       * @return {@link AndroidCommandResult}
       */
      private AndroidCommandResult getRotation() {
        String res = null;
        final UiDevice d = UiDevice.getInstance();
        final OrientationEnum currentRotation = OrientationEnum.fromInteger(d
            .getDisplayRotation());
        Logger.debug("Current rotation: " + currentRotation);
        switch (currentRotation) {
          case ROTATION_0:
          case ROTATION_180:
            res = "PORTRAIT";
            break;
          case ROTATION_90:
          case ROTATION_270:
            res = "LANDSCAPE";
            break;
        }
    
        if (res != null) {
          return getSuccessResult(res);
        } else {
          return getErrorResult("Get orientation did not complete successfully");
        }
      }
    
      /**
       * Set the desired rotation
       * 
       * @param orientation
       *          The rotation desired (LANDSCAPE or PORTRAIT)
       * @return {@link AndroidCommandResult}
       * @throws RemoteException
       * @throws InterruptedException
       */
      private AndroidCommandResult handleRotation(final String orientation)
          throws RemoteException, InterruptedException {
        final UiDevice d = UiDevice.getInstance();
        OrientationEnum desired;
        OrientationEnum current = OrientationEnum.fromInteger(d
            .getDisplayRotation());
    
        Logger.debug("Desired orientation: " + orientation);
        Logger.debug("Current rotation: " + current);
    
        if (orientation.equalsIgnoreCase("LANDSCAPE")) {
          switch (current) {
            case ROTATION_0:
              d.setOrientationRight();
              desired = OrientationEnum.ROTATION_270;
              break;
            case ROTATION_180:
              d.setOrientationLeft();
              desired = OrientationEnum.ROTATION_270;
              break;
            default:
              return getSuccessResult("Already in landscape mode.");
          }
        } else {
          switch (current) {
            case ROTATION_90:
            case ROTATION_270:
              d.setOrientationNatural();
              desired = OrientationEnum.ROTATION_0;
              break;
            default:
              return getSuccessResult("Already in portrait mode.");
          }
        }
        current = OrientationEnum.fromInteger(d.getDisplayRotation());
        // If the orientation has not changed,
        // busy wait until the TIMEOUT has expired
        final int TIMEOUT = 2000;
        final long then = System.currentTimeMillis();
        long now = then;
        while (current != desired && now - then < TIMEOUT) {
          Thread.sleep(100);
          now = System.currentTimeMillis();
          current = OrientationEnum.fromInteger(d.getDisplayRotation());
        }
        if (current != desired) {
          return getErrorResult("Set the orientation, but app refused to rotate.");
        }
        return getSuccessResult("Rotation (" + orientation + ") successful.");
      }
    }
    

    这个事件有点小复杂哈,当初研究uiautomator源代码时就被它折腾的不行。也仅仅实验了左和上的方向成功。

    没办法,既然又遇到了,那就仅仅能纯理论讲啦。


    execute方法中。首先推断參数中是否含有orientation,假设含有调用handleRotation。否则调用getRotation。


    所以execute又分流到上面的2个方法中。


    handleRotation


    这样的情况是參数里含有orientation,此时。我们来看看该方法中做了哪些事。


    final UiDevice d = UiDevice.getInstance();
        OrientationEnum desired;
        OrientationEnum current = OrientationEnum.fromInteger(d
            .getDisplayRotation());
    


    首先获取当前设备的方向,然后初始化一个私有变量,以备后用。当中OrientationEnum枚举类里定义了4个方向,fromInteger方法是依据整数值得到对应的枚举值,当中各个值的意思。


    public enum OrientationEnum {
      ROTATION_0(0), ROTATION_90(1), ROTATION_180(2), ROTATION_270(3);
    
      public static OrientationEnum fromInteger(final int x) {
        switch (x) {
          case 0:
            return ROTATION_0;
          case 1:
            return ROTATION_90;
          case 2:
            return ROTATION_180;
          case 3:
            return ROTATION_270;
        }
        return null;
      }


    ROTATION_0:你正常查看手机时,竖屏。此时屏幕的方向为0度。此时的power键在顶端。

    例如以下:



    ROTATION_90:你将上面的屏幕向右顺时针旋转90度,此时设备旋转角度为90度,此时我的power键在右端。假设此时你的设备能够自己主动旋转屏幕的话。你屏幕里面的内容应该是什么样的?例如以下所看到的




    ROTATION_180:从90度角再向下顺时针旋转90度。此时我的power键在下端。此时的角度为180.因为我的手机禁止了这样的自由旋转,所以此时的屏幕展如今我的面前是这样一番景象:




    ROTATION_270:从180度再顺时针想左旋转90度。此时我power键在左边。此时为270度。展如今我面前的图例如以下:




    假设你理解了上面4个keyword的意思。那么以下理解代码就非常easy啦。


    handleRotation方法里做完初始化操作以后。就要推断client要求是横屏还是竖屏。假设是横屏,处理例如以下:


    if (orientation.equalsIgnoreCase("LANDSCAPE")) {
          switch (current) {
            case ROTATION_0:
              d.setOrientationRight();
              desired = OrientationEnum.ROTATION_270;
              break;
            case ROTATION_180:
              d.setOrientationLeft();
              desired = OrientationEnum.ROTATION_270;
              break;
            default:
              return getSuccessResult("Already in landscape mode.");
          }
        }

    假设是横屏的话,那么仅仅须要处理屏幕处于0度和180度的情况,由于90度和270度都已经是横屏啦,自然不须要再处理。


    假设是ROTATION_0,说明设备朝上,此时想要横屏,自然是顺时针向右旋转一下屏幕。此时,正常情况下能够旋转的话。屏幕里的视图应该是从左到右的,所以desired的值才会被设置为ROTATION_270.所以要分清屏幕的角度和视图的角度。

    以下就是向右顺时针旋转90度后,里面的视图是270度的。此时power键在右端。



    假设是ROTATION_180度,说明设备拿反了,power键朝下。此时你向左顺时针旋转90度或者向右逆时针旋转90度。都能达到横屏的效果。源代码里是向左旋转的,此时power键朝左,视图和上面是一样的,desired的值为ROTATION——270.


    ====================================================================================================================================


    假设client传递过来的命令想要的是竖屏。就要走else里的代码块:


    else {
          switch (current) {
            case ROTATION_90:
            case ROTATION_270:
              d.setOrientationNatural();
              desired = OrientationEnum.ROTATION_0;
              break;
            default:
              return getSuccessResult("Already in portrait mode.");
          }
        }

    此时仅仅要处理90度和270的情况。我们要把它变为ROTATION_0的情况,d.setOrientationNatural()是设置设备转到自然方向,该方向就是设备初始设置的方向。说明通常的设备横屏的2个方向能够旋转。竖屏方向就仅仅有一个方向能够旋转。上面的处理完成后,方法会做一个推断,推断是否旋转成功。


     current = OrientationEnum.fromInteger(d.getDisplayRotation());
        // If the orientation has not changed,
        // busy wait until the TIMEOUT has expired
        final int TIMEOUT = 2000;
        final long then = System.currentTimeMillis();
        long now = then;
        while (current != desired && now - then < TIMEOUT) {
          Thread.sleep(100);
          now = System.currentTimeMillis();
          current = OrientationEnum.fromInteger(d.getDisplayRotation());
        }
        if (current != desired) {
          return getErrorResult("Set the orientation, but app refused to rotate.");
        }
        return getSuccessResult("Rotation (" + orientation + ") successful.");

    首先获得此时屏幕的方向,然后推断一下与预期的是否同样。假设不同样,等待2秒钟,再获取一次屏幕的方向,假设经过这么一次验证完成后。当前的屏幕方向仍然和预期的不同样,那么就返回旋转失败的消息给client。假设同样的话,就返回旋转成功的消息给client。


    到此为止handleRotation处理完成。以下处理參数里不含有orientation的情况。


    getRotation


    该方法中就是依据当前的屏幕的方向得到横屏还是竖屏,将结果返回给client。

    非常easy。



    总结


    通过上面的分析。说明client关于屏幕方向的命令有2种:

    • 获取屏幕的方向
    • 改变屏幕的方向


    大家要特别主要选择方向的定义,设备的方向和里面视图的方向的差别。






  • 相关阅读:
    闭包
    内置函数
    595926265989859
    C错题集锦
    C中改变指针的指向
    /dev/zero
    define的高级用法
    (转)Linux ./configure --prefix命令
    (转)linux下tty,控制台,虚拟终端,串口,console(控制台终端)详解
    内核驱动模块的Makefile模板
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7089907.html
Copyright © 2011-2022 走看看