九宫格解锁是很多 app 测试都会遇到的,解锁九宫格的原理就是用 appium 的 actions 的 moveto 方法连续移动坐标偏移量,由于九宫格都是标准的,九个点,所以通过九宫格第一个起点坐标就可以计算出偏移量。因此我封装了一个通用解锁九宫格的方法,简单便捷,特分享出来避免重复造轮子。方法支持 ANDROID,和 IOS(9.1),由于 IOS9.1 以上采用 XCUTESTDRIVER,底层不支持连续移动坐标的手势操作,故暂不支持 IOS 9.1 以上的设备解锁。还不清楚是 APPIUM 底层 XCUTESTDRIVER 不支持还是 WDA 不提供连续移动坐标手势支持。
/**
* 输入格式 {(300,500,100,200)/(1,3,5,7,9)}
* 300,500 :第一个点的x,y坐标,100,200 是横竖点坐标相对间隔
* 1,3,5,7,9是Z子解锁路径
* 起点坐标和横竖点坐标,均可通过webdriver webelement API webElement.getLocation()计算出。
* @param inputData
*/
public void drawScreenLockPassWd(String inputData,WebDriver driver){
try {
if (!inputData.contains("/")){
log.error("格式不正确");
}else {
log.info("开始解锁");
String[] strArray=inputData.split("/")[0].replace("{","").replace("(","").replace(")","").split(",");
int x=Integer.parseInt(strArray[0]);
int y=Integer.parseInt(strArray[1]);
int spaceX=Integer.parseInt(strArray[2]);
int spaceY=Integer.parseInt(strArray[3]);
String[] strArray2=inputData.split("/")[1].replace("}","").replace("(","").replace(")","").split(",");
int[] dot=new int[strArray2.length];
for (int i=0;i<strArray2.length;i++){
dot[i]=Integer.parseInt(strArray2[i]);
}
drawScreenLockPassWd(x,y,spaceX,spaceY,dot,driver);
}
}catch (Exception e){
log.error("解锁失败");
throw e;
}
}
/**
*
* @param x
* @param y
* @param spaceX
* @param spaceY
* @param dotPos 点位置列表
*/
private void drawScreenLockPassWd(int x, int y, int spaceX,int spaceY,int[] dotPos,WebDriver driver){
try {
List<Position> positionList=new ArrayList<>();
for (int i=0;i<dotPos.length;i++){
Position position=getPositionToLockScreenPassWd(x,y,spaceX,spaceY,dotPos[i]);
positionList.add(position);
}
TouchAction touchAction=null;
if (driver instanceof AndroidDriver){
touchAction=new TouchAction((AndroidDriver)driver);
}else if (driver instanceof IOSDriver){
touchAction=new TouchAction((IOSDriver)driver);
}
TouchAction touchAction1=touchAction.press(positionList.get(0).getX(),positionList.get(0).getY()).waitAction(500);
for (int i=1;i<positionList.size();i++){
switch (dotPos[i]-dotPos[i-1]){
case 1://恒向右
x=spaceX;
y=0;
break;
case -1://恒向左
x=-spaceX;
y=0;
break;
case 3://竖向下
x=0;
y=spaceY;
break;
case -3://竖向上
y=-spaceY;
x=0;
break;
case 2://斜对角左向下
x=-spaceX;
y=spaceY;
break;
case 4://斜对角右向下
x=spaceX;
y=spaceY;
break;
case -2://斜对角右向上
x=spaceX;
y=-spaceY;
break;
case -4://斜对角左向上
x=-spaceX;
y=-spaceY;
break;
}
log.info("第"+i+"次按坐标偏移量("+x+","+y+")"+"滑动");
if (driver instanceof IOSDriver){//ios滑动模式
IOSDriver iosDriver=(IOSDriver)driver;
TouchAction touchAction2=null;
String uiautomationName=iosDriver.getAutomationName();
if (uiautomationName!=null){//Xcuitest模式 适用于ios9.3以上手机
touchAction1=touchAction1.moveTo(x,y).waitAction(500);
if (i==positionList.size()-1){
touchAction1.release().perform();
break;
}
}else {
touchAction2=touchAction1.moveTo(x,y).waitAction(500);
if (i==positionList.size()-1){
touchAction2.release().perform();
break;
}
}
}else {
TouchAction touchAction2=touchAction1.moveTo(x,y).waitAction(500);
if (i==positionList.size()-1){
touchAction2.release().perform();
break;
}
}
}
}catch (Exception e){
log.info("没有找到解锁控件");
throw e;
}
}
/**
* 获取锁屏密码坐标
* @param x x轴
* @param y y轴
* @param spaceX 横向间隔
*@param spaceX 纵向间隔
* @param pos 第几个点
* @return
*/
private Position getPositionToLockScreenPassWd(int x, int y, int spaceX, int spaceY, int pos){
Position position=new Position();
switch (pos){
case 1:case 2:case 3://第一行
x=x+(pos-1)*spaceX;
position.setX(x);
position.setY(y);//恒向纵坐标相同
break;
case 4:case 5:case 6://第二行
y=y+spaceY;
x=x+(pos-3-1)*spaceX;
position.setX(x);
position.setY(y);
break;
case 7:case 8:case 9://第三行
y=y+2*spaceY;
x=x+(pos-6-1)*spaceX;
position.setX(x);
position.setY(y);
break;
}
return position;
}