为毛一到下班公司周边的摩拜单车都没有!约不到! 作为 IT dog 不甘心! 写个自动约车程序吧,公司测试机器闲着也是闲着 跑起来~
本来想通过抓接口,找找漏洞,搞不定呀 那就 UI 模拟吧。。。
UiAutomator Viewer 打开看一看,地图上单车坐标点抓不到 肿么办,如何才能约到离我最近的单车呢??突然发现定位后我的坐标总是在屏幕正中间,嘿嘿~ 那就以屏幕正中为中心,画一个矩形,做一个坐标点的 NXN 阶矩阵,从中心点向外层傻瓜式遍历得了~~反正不是我点点点
主测试类
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
import com.le.framework.uitl.Constant;
import com.le.framework.uitl.UiAutomatorUtil;
import com.le.uitest.testcase.base.Base;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by fj on 16/11/29.
* 摩拜单车自动约车 havefun^_^
*/
public class AutoMobike extends Base {
private static final String resourcePackage = "com.mobike.mobikeapp";
private static final int select_area = 0;//筛选范围:0 全部单车;1 Mobike;2 Mobike Lite
private static final int N = 20;//遍历坐标点密度 10~100
@BeforeClass
public static void init() throws Exception {
//亮屏解锁
// Launcher.unlock(mDevice);
//进入摩拜单车app
UiAutomatorUtil.goToApp(resourcePackage);
}
@Test
public void reserve() throws Exception {
//选择单车类型
List<UiObject2> list = mDevice.wait(Until.findObjects(By.res(resourcePackage, "id_index_gallery_item_text")), 10000);//10s
list.get(select_area).click();
Thread.sleep(2000);
//定位当前位置到屏幕中心点
mDevice.findObject(By.res(resourcePackage, "map_location_button")).click();
Thread.sleep(1000);
List<String> points = this.getPoints();
Log.e(Constant.Tags.uitest, Arrays.toString(points.toArray()));
//从中心点向外逆序遍历坐标集合
for (int i = points.size() - 1; i >= 0; i--) {
String point = points.get(i);
//如果预约成功了,就等待取消预约或保留时间到期后重新刷新坐标点;否则继续遍历坐标点
if (bikeExist(point) && reserveOne()) {
while (mDevice.hasObject(By.res(resourcePackage, "booking_cancel_button"))) {
Thread.sleep(1000);
}
reserve();
}
}
}
//判断坐标点point是否有单车
private boolean bikeExist(String point) throws Exception {
String[] xy = point.split(",");
UiAutomatorUtil.clickByPoint(mDevice, Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
return mDevice.wait(Until.hasObject(By.res(resourcePackage, "request_booking_button")), 500);
}
//预约15分钟
private boolean reserveOne() {
mDevice.findObject(By.res(resourcePackage, "request_booking_button")).click();
if (mDevice.wait(Until.hasObject(By.res(resourcePackage, "booking_cancel_button")), 1000)) {
return true;
} else {
return false;
}
}
private List<String> getPoints() {
//获取屏幕长宽
int height = mDevice.getDisplayHeight();
int width = mDevice.getDisplayWidth();
Log.e(Constant.Tags.uitest, width + ":" + height);
//取height(1/4~3/4) width(0~width)区域,生成NXN矩阵坐标点
int width_start = 0;
int height_start = height / 4;
int width_cut = width / N;
int height_cut = (height * 3 / 4 - height_start) / N;
Log.e(Constant.Tags.uitest, width_cut + ":" + height_cut);
String[][] points = new String[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
points[i][j] = width_start + "," + height_start;
width_start += width_cut;
}
height_start += height_cut;
width_start = 0;
}
//获取从外向内顺时针遍历后的矩阵
return everyLap(points, 0, points.length - 1);
}
/**
* 遍历一圈
*
* @param startPoint 起点
* @param endPoint 终点
*/
private static List<String> oneLap(String[][] data, List<String> res, int startPoint, int endPoint) {
for (int i = startPoint; i <= endPoint; i++) {
res.add(data[startPoint][i]);
if (i == endPoint) {
for (int j = startPoint + 1; j <= endPoint; j++) {
res.add(data[j][endPoint]);
if (j == endPoint) {
for (int i2 = endPoint - 1; i2 >= startPoint; i2--) {
res.add(data[endPoint][i2]);
if (i2 == startPoint) {
for (int j2 = endPoint - 1; j2 > startPoint; j2--) {
res.add(data[j2][startPoint]);
}
}
}
}
}
}
}
return res;
}
/**
* 遍历每一圈
**/
private static List<String> everyLap(String[][] data, int startPoint, int endPoint) {
List<String> res = new ArrayList<String>();
while (startPoint <= endPoint) {
System.out.println("start= " + startPoint + " end= " + endPoint);
res = oneLap(data, res, startPoint++, endPoint--);
}
return res;
}
}
工具类
import android.content.Context;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
/**
* Created by fj on 16/11/29.
*/
public class UiAutomatorUtil {
/**
* 获取测试程序自身的packageName
*/
public static String getTargetPackageName() {
return InstrumentationRegistry.getTargetContext().getPackageName();
}
public static Context getContext() {
return InstrumentationRegistry.getTargetContext();
}
/**
* 根据packageName启动一个应用
*/
public static boolean goToApp(String packageName) {
Context context = InstrumentationRegistry.getContext();
final Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
return device.wait(Until.hasObject(By.pkg(packageName).depth(0)), 5000);
}
}