Added support for element based swiping.

This commit is contained in:
xuru
2013-04-08 11:39:52 -05:00
parent f3720f7faf
commit de3fdfff92
6 changed files with 214 additions and 16 deletions

1
.gitignore vendored
View File

@@ -28,3 +28,4 @@ app/android/AndroidManifest.xml
.*~
*~
uiautomator/bootstrap/target/
org.eclipse.ltk.core.refactoring.prefs

View File

@@ -1,6 +1,8 @@
package io.appium.android.bootstrap;
import io.appium.android.bootstrap.exceptions.InvalidCoordinatesException;
import io.appium.android.bootstrap.exceptions.NoAttributeFoundException;
import io.appium.android.bootstrap.utils.Point;
import android.graphics.Rect;
import com.android.uiautomator.core.UiObject;
@@ -29,6 +31,63 @@ public class AndroidElement {
return el.click();
}
public Point getAbsolutePosition(final Double X, final Double Y)
throws UiObjectNotFoundException, InvalidCoordinatesException {
final Point point = new Point(X, Y);
return getAbsolutePosition(point, false);
}
public Point getAbsolutePosition(final Double X, final Double Y,
final boolean boundsChecking) throws UiObjectNotFoundException,
InvalidCoordinatesException {
final Point point = new Point(X, Y);
return getAbsolutePosition(point, boundsChecking);
}
public Point getAbsolutePosition(final Point point)
throws UiObjectNotFoundException, InvalidCoordinatesException {
return getAbsolutePosition(point, false);
}
public Point getAbsolutePosition(final Point point,
final boolean boundsChecking) throws UiObjectNotFoundException,
InvalidCoordinatesException {
final Rect rect = el.getBounds();
final Point pos = new Point();
if (point.x == 0) {
pos.x = rect.width() * 0.5 + rect.left;
} else if (point.x <= 1) {
pos.x = rect.width() * point.x + rect.left;
} else {
pos.x = rect.left + point.x;
}
if (boundsChecking == true) {
if (pos.x > rect.right || pos.x < rect.left) {
throw new InvalidCoordinatesException("X coordinate ("
+ pos.x.toString() + " is outside of element rect: "
+ rect.toShortString());
}
}
if (point.y == 0) {
pos.y = rect.height() * 0.5 + rect.top;
} else if (point.y <= 1) {
pos.y = rect.height() * point.y + rect.top;
} else {
pos.y = rect.left + point.y;
}
if (boundsChecking == true) {
if (pos.y > rect.bottom || pos.y < rect.top) {
throw new InvalidCoordinatesException("Y coordinate ("
+ pos.y.toString() + " is outside of element rect: "
+ rect.toShortString());
}
}
return pos;
}
public boolean getBoolAttribute(final String attr)
throws UiObjectNotFoundException, NoAttributeFoundException {
boolean res = false;
@@ -98,4 +157,5 @@ public class AndroidElement {
public boolean setText(final String text) throws UiObjectNotFoundException {
return el.setText(text);
}
}

View File

@@ -1,5 +1,8 @@
package io.appium.android.bootstrap;
import io.appium.android.bootstrap.exceptions.InvalidCoordinatesException;
import io.appium.android.bootstrap.utils.Point;
import java.util.ArrayList;
import org.json.JSONException;
@@ -38,6 +41,36 @@ public abstract class CommandHandler {
return retPos;
}
protected static Point GetAbsPos(final Point point)
throws InvalidCoordinatesException {
final UiDevice d = UiDevice.getInstance();
final Point retPos = new Point(point); // copy inputed point
final Double width = new Double(d.getDisplayWidth());
if (point.x < 1) {
retPos.x = width * point.x;
}
if (retPos.x > width || retPos.x < 0) {
throw new InvalidCoordinatesException("X coordinate ("
+ retPos.x.toString() + " is outside of screen width: "
+ width.toString());
}
final Double height = new Double(d.getDisplayHeight());
if (point.y < 1) {
retPos.y = height * point.y;
}
if (retPos.y > height || retPos.y < 0) {
throw new InvalidCoordinatesException("Y coordinate ("
+ retPos.y.toString() + " is outside of screen height: "
+ height.toString());
}
return retPos;
}
/**
* Abstract method that handlers must implement.
*

View File

@@ -0,0 +1,14 @@
package io.appium.android.bootstrap.exceptions;
/**
* An exception that is thrown when an invalid coordinate is used.
*
* @author <a href="https://github.com/xuru">xuru</a>
* @param msg
* A descriptive message describing the error.
*/
public class InvalidCoordinatesException extends Exception {
public InvalidCoordinatesException(final String msg) {
super(msg);
}
}

View File

@@ -2,14 +2,19 @@ package io.appium.android.bootstrap.handler;
import io.appium.android.bootstrap.AndroidCommand;
import io.appium.android.bootstrap.AndroidCommandResult;
import io.appium.android.bootstrap.AndroidElement;
import io.appium.android.bootstrap.CommandHandler;
import io.appium.android.bootstrap.Logger;
import io.appium.android.bootstrap.exceptions.ElementNotInHashException;
import io.appium.android.bootstrap.exceptions.InvalidCoordinatesException;
import io.appium.android.bootstrap.utils.Point;
import java.util.ArrayList;
import java.util.Hashtable;
import org.json.JSONException;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObjectNotFoundException;
/**
* This handler is used to swipe.
@@ -33,26 +38,40 @@ public class Swipe extends CommandHandler {
public AndroidCommandResult execute(final AndroidCommand command)
throws JSONException {
final Hashtable<String, Object> params = command.params();
final Double startX = Double.parseDouble(params.get("startX").toString());
final Double startY = Double.parseDouble(params.get("startY").toString());
final Double endX = Double.parseDouble(params.get("endX").toString());
final Double endY = Double.parseDouble(params.get("endY").toString());
final Point start = new Point(params.get("startX"), params.get("startY"));
final Point end = new Point(params.get("endX"), params.get("endY"));
final Integer steps = (Integer) params.get("steps");
final UiDevice device = UiDevice.getInstance();
Point absStartPos = new Point();
Point absEndPos = new Point();
if (command.isElementCommand()) {
// Can this command run on the element it's self?
// swipe on an element is handled by 4 different commands:
// swipeDown, swipeLeft, swipeRight, and swipeUp
// We have to figure out which to call and position it correctly...
try {
final AndroidElement el = command.getElement();
absStartPos = el.getAbsolutePosition(start);
absEndPos = el.getAbsolutePosition(end, false);
} catch (final ElementNotInHashException e) {
return getErrorResult(e.getMessage());
} catch (final UiObjectNotFoundException e) {
return getErrorResult(e.getMessage());
} catch (final InvalidCoordinatesException e) {
return getErrorResult(e.getMessage());
}
} else {
final UiDevice device = UiDevice.getInstance();
final Double[] coords = { startX, startY, endX, endY };
final ArrayList<Integer> posVals = absPosFromCoords(coords);
final boolean rv = device.swipe(posVals.get(0), posVals.get(1),
posVals.get(2), posVals.get(3), steps);
return getSuccessResult(rv);
try {
absStartPos = GetAbsPos(start);
absEndPos = GetAbsPos(end);
} catch (final InvalidCoordinatesException e) {
return getErrorResult(e.getMessage());
}
}
return getErrorResult("Error in swiping...");
Logger.info("Swiping from " + absStartPos.toString() + " to "
+ absEndPos.toString() + " with steps: " + steps.toString());
final boolean rv = device.swipe(absStartPos.x.intValue(),
absStartPos.y.intValue(), absEndPos.x.intValue(),
absEndPos.y.intValue(), steps);
return getSuccessResult(rv);
}
}

View File

@@ -0,0 +1,71 @@
package io.appium.android.bootstrap.utils;
public class Point {
public Double x;
public Double y;
public Point() {
x = 0.0;
y = 0.0;
}
public Point(final Double x, final Double y) {
this.x = x;
this.y = y;
}
public Point(final Object x, final Object y) {
this.x = Double.parseDouble(x.toString());
this.y = Double.parseDouble(y.toString());
}
public Point(final Point other) {
x = other.x;
y = other.y;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Point other = (Point) obj;
if (x == null) {
if (other.x != null) {
return false;
}
} else if (!x.equals(other.x)) {
return false;
}
if (y == null) {
if (other.y != null) {
return false;
}
} else if (!y.equals(other.y)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (x == null ? 0 : x.hashCode());
result = prime * result + (y == null ? 0 : y.hashCode());
return result;
}
@Override
public String toString() {
return "[x=" + x + ", y=" + y + "]";
}
}