mirror of
https://github.com/appium/appium.git
synced 2026-01-29 13:49:01 -06:00
Added support for element based swiping.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -28,3 +28,4 @@ app/android/AndroidManifest.xml
|
||||
.*~
|
||||
*~
|
||||
uiautomator/bootstrap/target/
|
||||
org.eclipse.ltk.core.refactoring.prefs
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user