android模拟点击程序并截图

本文章主要内容为如何在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();
}

“android模拟点击程序并截图”的一个回复

  1. 你好,能实现更复杂的功能吗?比如截长图,模拟用户做点击、输入内容等操作

    方便的话加QQ,联系一下,我QQ:404230497

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注