本文章主要内容为如何在PC或服务器上为指定android程序模拟随机点击并对其进行截图。
主要解决的问题是获取android设备上当前时间所显示的内容,截图后保存到本地(服务器端),而非android设备上。
主要利用的工具为chimpchat.jar与ddmlib.jar两个jar包,这两个jar包包含在android sdk内,一般在sdk/tools/lib/下,这两个jar包所完成的工作不过是封装了一些协议及一些常用操作,如操纵设备点击、拖动等,也包含了将命令(cmd)在android设备上执行的功能。
核心代码如下,代码展示了对一个应用程序进行随机点击并截图保存,里边用到了monkey自动化测试工具来完成随机点击事件:
ChimpChat c = ChimpChat.getInstance(); //等待设备连接 IChimpDevice paramIChimpDevice = c.waitForConnection(); //截图 paramIChimpDevice.takeSnapshot(); //cmd内容为执行monkey命令 paramIChimpDevice.shell(cmd, 5 * 1000 * 60);
具体代码如下:
AutoApp.java
package com.surfilter.autoapp; import com.android.chimpchat.ChimpChat; import com.android.chimpchat.core.IChimpDevice; import com.surfilter.autoapp.action.MonkeyAction; import com.surfilter.autoapp.screenshot.ScreenShot; /** * @author liu * */ public class AutoApp { private static long DEVICE_CONNECTION_TIMEOUT = 10000l; private static int MONKEY_WAIT_TIMEOUT = 1000 * 5 * 60; public static void main(String[] args) { String appName = "woxiu"; String deviceId = "android"; String packageName = "com.wole56.ishow"; String path = "E:\\snapshot\\"+ appName +"\\"; //阻塞执行,执行过程中设备不能做其他事情 runApp(deviceId, path, packageName, appName); } /** * 在指定设备上运行程序并随机点击后截图 * @param deviceId * @param path * @param monkeyWaitTimeout * @param packageName * @param appName */ public static void runApp(String deviceId, String path, String packageName, String appName){ ChimpChat c = ChimpChat.getInstance(); final IChimpDevice paramIChimpDevice = c.waitForConnection(/*DEVICE_CONNECTION_TIMEOUT, deviceId*/); final ScreenShot ss = new ScreenShot(paramIChimpDevice, path, appName); //回调中停止截图,并且关闭android设备上的命令监听服务 Callback callback = new Callback() { @Override public void callback() { System.out.println("over..."); ss.endTakeShot(); paramIChimpDevice.dispose(); } }; MonkeyAction ma = new MonkeyAction(paramIChimpDevice, packageName, MONKEY_WAIT_TIMEOUT, callback); ss.beginTakeShot(); ma.action(); } }
MonkeyAction.java
package com.surfilter.autoapp.action; import com.android.chimpchat.core.IChimpDevice; import com.surfilter.autoapp.Callback; public class MonkeyAction { private static String MONKEY_CMD = "monkey"; private IChimpDevice paramIChimpDevice; private String packageName; private int shellWaitTimestamp = 5 * 1000 * 60; private long seed = 10000; private long executeTimes = 50000; private long executeSepratTime = 100; private boolean ignoreInfos = true; private Callback callback; public MonkeyAction(IChimpDevice paramIChimpDevice, String packageName, int shellWaitTimestamp, Callback callback) { this.paramIChimpDevice = paramIChimpDevice; this.packageName = packageName; this.callback = callback; this.shellWaitTimestamp = shellWaitTimestamp; } /** * 开始执行Monkey * @return */ public boolean action(){ try{ paramIChimpDevice.shell(getExecuteCmd(), shellWaitTimestamp); clean(); if(callback != null){ callback.callback(); } return true; }catch(Exception e){ e.printStackTrace(); return false; } } private void clean(){ //TODO:需要清理monkey进程 //paramIChimpDevice.shell("ps |grep monkey", 3000); } private String getExecuteCmd() { StringBuilder sb = new StringBuilder(); sb.append(MONKEY_CMD); sb.append(" -v "); sb.append(" -p "); sb.append(packageName); sb.append(" -s "); sb.append(seed); if(executeSepratTime != 0){ sb.append(" --throttle "); sb.append(executeSepratTime); } if(ignoreInfos){ sb.append(" --ignore-crashes "); sb.append(" --ignore-timeouts "); sb.append(" --ignore-security-exceptions "); sb.append(" --kill-process-after-error "); } sb.append(executeTimes); return sb.toString(); } public static void main(String[] args) { System.out.println(new MonkeyAction(null, "com.tencent.qq", 5 * 1000, null).getExecuteCmd()); } }
ScreenShot.java
package com.surfilter.autoapp.screenshot; import com.android.chimpchat.core.IChimpDevice; import com.android.chimpchat.core.IChimpImage; public class ScreenShot { private IChimpDevice paramIChimpDevice; private String path; private String fileNamePrefix; private int fileCount = 0; private String fileType = "png"; public ScreenShot(IChimpDevice paramIChimpDevice, String path, String fileNamePrefix) { this.paramIChimpDevice = paramIChimpDevice; this.path = path; this.fileNamePrefix = fileNamePrefix; } private boolean isBegined = false; private boolean isStoped = false; /** * 开始截图 * @return */ public boolean beginTakeShot(){ if(!isBegined){ isBegined = true; new Thread(new Runnable() { @Override public void run() { while(true){ try{ if(!isStoped){ takeShot(); } Thread.sleep(1000); }catch(Exception e){ e.printStackTrace(); } } } }).start(); }else{ System.out.println("已经开始截图了.."); } return true; } /** * 停止截图 * @return */ public boolean endTakeShot(){ isStoped = true; return isStoped; } private boolean takeShot() { boolean success = false; IChimpImage chimpImage = paramIChimpDevice.takeSnapshot(); if(chimpImage == null){ return success; } if (needSave(chimpImage)) { success = chimpImage.writeToFile(genFileName(), fileType); if (success) { fileCount++; } } return success; } private String genFileName() { return path + "/" + fileNamePrefix + "_" + fileCount + "." + fileType; } private IChimpImage lastImage; private boolean needSave(IChimpImage chimpImage) { boolean flag = false; if(lastImage != null){ flag = chimpImage.sameAs(lastImage, 0.8); lastImage = chimpImage; }else{ lastImage = chimpImage; } return !flag; } }
Callback.java
package com.surfilter.autoapp; public interface Callback{ public void callback(); }
你好,能实现更复杂的功能吗?比如截长图,模拟用户做点击、输入内容等操作
方便的话加QQ,联系一下,我QQ:404230497