[英]Android Screen Capture using root view
我正在尝试捕获屏幕
View decorView = activity.getWindow().getDecorView();
decorView.setDrawingCacheEnabled(true);
Bitmap bitmap = decorView.getDrawingCache();
一切正常,我可以截屏了。 但是对于一种情况,我面临一个问题。 但是,当存在Dialog片段时,不会捕获Dialog片段的视图,但是会捕获部分可见的背景活动视图,就像在最顶层的活动的根视图一样。
但是,当存在Dialog片段时,不会捕获Dialog片段的视图,但是会捕获部分可见的背景活动视图,就像在最顶层的活动的根视图一样。
那是因为Dialog
在单独的窗口中。 我对此一无所知。
您可以在反射的帮助下获取应用程序所有窗口的装饰视图列表。 该列表不仅包含活动的装饰视图,还包含对话框和弹出窗口的装饰视图。
void processDialogWindow(Context context) {
WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Field globalField = Class.forName("android.view.WindowManagerImpl").getDeclaredField("mGlobal");
globalField.setAccessible(true);
Object globalFieldValue = globalField.get(windowManager);
List<?> viewsFieldValue = getViews(globalFieldValue);
for (int i = viewsFieldValue.size() - 1; i >= 0; i--) {
View decorView = (View)viewsFieldValue.get(i);
WindowManager.LayoutParams castedParams = (WindowManager.LayoutParams)decorView.getLayoutParams();
if (castedParams.type == WindowManager.LayoutParams.TYPE_APPLICATION) { // Dialog
//TODO: get decorView screenshot.
}
}
}
List<?> getViews(Object globalWindowManager) throws NoSuchFieldException, IllegalAccessException {
Field viewsField = globalWindowManager.getClass().getDeclaredField("mViews");
viewsField.setAccessible(true);
Object viewsFieldValue = viewsField.get(globalWindowManager);
if (viewsFieldValue instanceof List<?>)
return (List<?>)viewsFieldValue;
else if (viewsFieldValue instanceof View[]) {
return new ArrayList<>(Arrays.asList((View[])viewsFieldValue));
}
return null;
}
我已经在Android 5、6和7上测试了这种方法。当然,当您使用反射时,应该检查某个字段的值是否不为null且确实具有预期的类型。 因此,可以在将来的Android版本中或通过设备供应商甚至在现有的Android版本中更改通过反射访问的内部数据结构。 为了简洁起见,我没有在此处添加对null或错误类型的检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.