码迷,mamicode.com
首页 > 其他好文 > 详细

bootstrap之Orientation

时间:2017-06-28 15:45:56      阅读:270      评论:0      收藏:0      [点我收藏+]

标签:sig   play   import   顺时针   handler   his   整数   消息   content   

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种:

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


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






bootstrap之Orientation

标签:sig   play   import   顺时针   handler   his   整数   消息   content   

原文地址:http://www.cnblogs.com/liguangsunls/p/7089907.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!