- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在使用 espresso 在 Android 中执行操作之前截取屏幕截图。
protected T performAction(ViewAction viewAction) {
ViewAction screenShotAction = new ScreenShotAction();
viewInteraction.perform(screenShotAction);
viewInteraction.perform(viewAction);
return returnGeneric();
}
例如,如果在我的测试中我执行了 click(),那么我会在执行 click() 之前截取设备的屏幕截图。
这是在 ScreenShotAction 类中获取屏幕截图的代码
@Override
public void perform(UiController uiController, View view) {
View rootView = view.getRootView();
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)) {
File picDir = new File(Environment.getExternalStorageDirectory() + "app_" + "test");
if (!picDir.exists()) {
picDir.mkdir();
}
rootView.setDrawingCacheEnabled(true);
rootView.buildDrawingCache(true);
Bitmap bitmap = rootView.getDrawingCache();
String fileName = "test.jpg";
File picFile = new File(picDir + "/" + fileName);
try {
picFile.createNewFile();
FileOutputStream picOut = new FileOutputStream(picFile);
bitmap = Bitmap.createBitmap(rootView.getWidth(), rootView.getHeight(), Bitmap.Config.ARGB_8888);
boolean saved = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, picOut);
if (saved) {
// good
} else {
// error
throw new Exception("Image not saved");
}
picOut.flush();
picOut.close();
} catch (Exception e) {
e.printStackTrace();
}
rootView.destroyDrawingCache();
}
}
我在手机的图片目录或任何其他目录中没有看到任何图像文件。我相信屏幕截图方法是可靠的,但不确定我是否正确调用了该方法。
viewInteraction.perform(screenShotAction) 是调用我的自定义 View 操作的正确方式吗?
请提前帮助并谢谢你。
最佳答案
您可以执行以下操作:
public class CaptureImage {
@SuppressWarnings("unused")
private static final String TAG = CaptureImage.class.getSimpleName();
private static final String NAME_SEPARATOR = "_";
private static final String EXTENSION = ".png";
private static final Object LOCK = new Object();
private static boolean outputNeedsClear = true;
private static final Pattern NAME_VALIDATION = Pattern.compile("[a-zA-Z0-9_-]+");
public static void takeScreenshot(View currentView, String className,
String methodName, @Nullable String prefix) {
methodName = methodName.replaceAll("[\\[\\](){}]", "");
if (!NAME_VALIDATION.matcher(methodName).matches()) {
throw new IllegalArgumentException(
"Name must match " + NAME_VALIDATION.pattern() +
" and " + methodName + " was received.");
}
Context context = InstrumentationRegistry.getTargetContext();
MyRunnable myRunnable = new MyRunnable(context, currentView, className, methodName, prefix);
Activity activity =
((Application)context.getApplicationContext()).getCurrentActivity();
activity.runOnUiThread(myRunnable);
}
private static class MyRunnable implements Runnable {
private View mView;
private Context mContext;
private String mClassName;
private String mMethodName;
private String mPrefix;
MyRunnable(Context context, View view, String className, String methodName, String prefix) {
mContext = context;
mView = view;
mClassName = className;
mMethodName = methodName;
mPrefix = prefix;
}
@TargetApi(VERSION_CODES.JELLY_BEAN_MR2)
public void run() {
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
if (uiAutomation == null) {
return;
}
OutputStream out = null;
Bitmap bitmap = null;
try {
String timestamp = new SimpleDateFormat("MM_dd_HH_mm_ss", Locale.ENGLISH)
.format(new Date());
File screenshotDirectory = getScreenshotFolder();
int statusBarHeight = getStatusBarHeightOnDevice();
bitmap = uiAutomation.takeScreenshot();
Bitmap screenshot = Bitmap.createBitmap(bitmap, 0, statusBarHeight,
mView.getWidth(), mView.getHeight() - statusBarHeight);
String screenshotName = mMethodName + NAME_SEPARATOR +
(mPrefix != null ? (mPrefix + NAME_SEPARATOR) : "") +
timestamp + EXTENSION;
Log.d("YOUR_TAG", "Screenshot name: " + screenshotName);
File imageFile = new File(screenshotDirectory, screenshotName);
out = new FileOutputStream(imageFile);
screenshot.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
} catch (Throwable t) {
Log.e("YOUR_LOG", "Unable to capture screenshot.", t);
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception ignored) {
}
if (bitmap != null) {
bitmap.recycle();
}
}
}
private int getStatusBarHeightOnDevice() {
int _StatusBarHeight = 0;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
mView.setDrawingCacheEnabled(true);
Bitmap screenShot = Bitmap.createBitmap(mView.getDrawingCache());
mView.setDrawingCacheEnabled(false);
if (screenShot != null) {
int StatusColor = screenShot.getPixel(0, 0);
for (int y = 1; y < (screenShot.getHeight() / 4); y++) {
if (screenShot.getPixel(0, y) != StatusColor) {
_StatusBarHeight = y - 1;
break;
}
}
}
if (_StatusBarHeight == 0) {
_StatusBarHeight = 50; // Set a default in case we don't find a difference
}
Log.d("YOUR_TAG", "Status Bar was measure at "
+ _StatusBarHeight + " pixels");
return _StatusBarHeight;
}
private File getScreenshotFolder() throws IllegalAccessException {
File screenshotsDir;
if (Build.VERSION.SDK_INT >= 21) {
// Use external storage.
screenshotsDir = new File(getExternalStorageDirectory(),
"screenshots");
} else {
// Use internal storage.
screenshotsDir = new File(mContext.getApplicationContext().getFilesDir(),
"screenshots");
}
synchronized (LOCK) {
if (outputNeedsClear) {
deletePath(screenshotsDir);
outputNeedsClear = false;
}
}
File dirClass = new File(screenshotsDir, mClassName);
File dirMethod = new File(dirClass, mMethodName);
createDir(dirMethod);
return dirMethod;
}
private void createDir(File dir) throws IllegalAccessException {
File parent = dir.getParentFile();
if (!parent.exists()) {
createDir(parent);
}
if (!dir.exists() && !dir.mkdirs()) {
throw new IllegalAccessException(
"Unable to create output dir: " + dir.getAbsolutePath());
}
}
private void deletePath(File path) {
if (path.isDirectory() && path.exists()) {
File[] children = path.listFiles();
if (children != null) {
for (File child : children) {
Log.d("YOUR_TAG", "Deleting " + child.getPath());
deletePath(child);
}
}
}
if (!path.delete()) {
// log message here
}
}
}
然后您可以从 ViewAction 或直接从测试用例类调用它:
查看操作类:
class ScreenshotViewAction implements ViewAction {
private final String mClassName;
private final String mMethodName;
private final int mViewId;
private final String mPrefix;
protected ScreenshotViewAction(final int viewId, final String className,
final String methodName, @Nullable final String prefix) {
mViewId = viewId;
mClassName = className;
mMethodName = methodName;
mPrefix = prefix;
}
@Override
public Matcher<View> getConstraints() {
return ViewMatchers.isDisplayed();
}
@Override
public String getDescription() {
return "Taking a screenshot.";
}
@Override
public void perform(final UiController aUiController, final View aView) {
aUiController.loopMainThreadUntilIdle();
final long startTime = System.currentTimeMillis();
final long endTime = startTime + 2000;
final Matcher<View> viewMatcher = ViewMatchers.withId(mViewId);
do {
for (View child : TreeIterables.breadthFirstViewTraversal(aView)) {
// found view with required ID
if (viewMatcher.matches(child)) {
CaptureImage.takeScreenshot(aView.getRootView(), mClassName,
mMethodName, mPrefix);
return;
}
}
aUiController.loopMainThreadForAtLeast(50);
}
while (System.currentTimeMillis() < endTime);
}
现在从您的测试用例类中,创建以下静态方法:
public static void takeScreenshot(int prefix) {
View currentView = ((ViewGroup)mActivity
.getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0);
String fullClassName = Thread.currentThread().getStackTrace()[3].getClassName();
String testClassName = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
String testMethodName = Thread.currentThread().getStackTrace()[3].getMethodName();
CaptureImage.takeScreenshot(currentView, testClassName, testMethodName,
String.valueOf(prefix));
}
public static ViewAction takeScreenshot(@Nullable String prefix) {
String fullClassName = Thread.currentThread().getStackTrace()[3].getClassName();
String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
String methodName = Thread.currentThread().getStackTrace()[3].getMethodName();
return new ScreenshotViewAction(getDecorView().getId(), className, methodName, prefix);
}
或者您可以从执行 View 操作中调用它:
takeScreenshot(0);
onView(withContentDescription(sContext
.getString(R.string.abc_action_bar_up_description)))
.perform(
ScreenshotViewAction.takeScreenshot(String.valueOf(1)),
click()
);
关于java - 编写自定义 Android ViewAction 以截取屏幕截图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28888635/
图像采集源除了显示控件(上一篇《.NET 控件转图片》有介绍从界面控件转图片),更多的是窗口以及屏幕。 窗口截图最常用的方法是GDI,直接上Demo吧: 1 private
我正在尝试编写一个程序来使用全局热键获取屏幕截图。下面是相应的代码: from datetime import datetime import os from pynput import keyboa
我正在构建一个应用程序,它应该为任何具有 Android 4 及更高版本的无根设备实现屏幕~镜像~,2 帧/秒就足够了。 我正在尝试使用 ADB“framebuffer:”命令来抓取设备屏幕截图 AD
如何使用 C++ 捕获屏幕截图?我将使用 Win32。 请不要使用 MFC 代码。 最佳答案 #include "windows.h" // should be less than and great
代码如下: import java.awt.Dimension; import java.awt.Rectangle; import java.awt.Robot; import java.aw
我目前正在构建一个 Google Chrome 扩展程序,该扩展程序可以从不同页面获取多个屏幕截图并将其发布到端点上。我遇到的问题是时间不对。我的意思是,在页面停止加载之前就太早截取屏幕截图了。其次,
我有一个 View Controller ,其中导航栏是透明的。我的下一个 View 是表格 View ,其中导航栏是白色的。 为了停止不需要的动画,我在表格 View 的“viewDidDissap
我正在尝试从多个 URL 制作屏幕截图。我的代码工作正常,但结果我得到了事件窗口的图像。但我需要带有浏览器顶部的完整屏幕截图(URL) file = open('links.txt', 'r', en
我正在尝试(并实现)获取屏幕截图: robot = new Robot(); BufferedImage biScreen = robot.createScreenCapture(rectScreen
是否有任何应用程序可以拍摄 android 设备的视频/屏幕截图。我知道在桌面上捕获屏幕视频/图像的软件很少,例如 camtasia、snagit。 Android 设备有类似的东西吗? 我知道使用
想要捕获可能处于非事件状态的选项卡的图像。 问题是,当使用此处显示的方法时,选项卡通常在捕获完成之前没有时间加载,从而导致失败。 chrome.tabs.update() 回调在标签页被捕获之前执行。
我想在新的 tkinter 窗口 (TopLevel) 中显示我的屏幕截图,但我不想将其保存在电脑上。当我保存它时它工作正常但是当我尝试从内存加载屏幕截图时出现错误:图像不存在。 我的主窗口是root
我正在 try catch 我当前所在的屏幕,因此当我覆盖下一个 View Controller 时,我可以使它成为它后面的 ImageView 并使其显示为半透明。这是有效的,但现在它在中间产生了一
我正在寻找将 docx(以及后来的 excel 和 powerpoint)文档的第一页转换为图像的方法。我宁愿不手动解析文档的整个 xml,因为这看起来工作量很大;) 所以我想我只是想收集一些关于如何
好吧,碰巧我正在编写一个程序来截取一些屏幕截图,并且在处理另一个进程已经在使用的文件时遇到了一些困难,希望有人能帮助我找到一种方法来“关闭”这个进程或启发我如何继续. //Create a new b
我即将在 App Store 上发布我的应用程序,我想截取我的应用程序的屏幕截图,但状态栏中没有所有信息,例如运营商和 Debug模式等。 我知道 Marshmallow 有一个 System UI
UIGraphicsBeginImageContext(self.reportList.frame.size); CGRect tableViewFrame = self.reportList.fra
是否有任何简洁的方法来访问 android 设备的屏幕截图以编程方式。我正在寻找大约 15-20fps。 我找到了一个代码android\generic\frameworks\base\service
好的,我正在尝试为多个网站运行多个屏幕截图!我已经获得了多个站点的一个屏幕截图,我还可以获得一个站点的多个 Viewport 屏幕截图,但我有 34 个站点需要这样做!那么有人知道用 casperjs
我正在为 iOS 制作一个贴纸包,在将其提交到 App Store 之前,我需要包含至少一张来自 5.5 英寸 iPhone 和 12.9 英寸 iPad Pro 的应用截图。这些都是我没有的设备。
我是一名优秀的程序员,十分优秀!