如何在Android中以编程方式截取Alert Dialog的屏幕截图

8
我看到了以下链接,它可以拍摄带有顶部答案的截图。
然而,我想让应用程序拍摄我向用户显示的Alert Dialog的截图,上述解决方案和下面的代码只会拍摄当前Alert Dialog后面的内容,因此不好用。
如果有人还没有阅读提供的链接,请查看以下正在使用的代码。
Date now = new Date();
    android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);

    try {
        // image naming and path  to include sd card  appending name you choose for file
        String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";

        // create bitmap screen capture
        View v1 = getWindow().getDecorView().getRootView();
        v1.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        File imageFile = new File(mPath);

        FileOutputStream outputStream = new FileOutputStream(imageFile);
        int quality = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
        outputStream.flush();
        outputStream.close();

        openScreenshot(imageFile);
    } catch (Throwable e) {
        // Several error may come out with file handling or OOM
        e.printStackTrace();
    }

编辑:根据要求提供对话框的代码

public void showCalc(String title, String message) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setCancelable(true);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.setPositiveButton("Capture + Open",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    //Remove Values From Inventory
                    captureScreenAndOpen();

                }
            });

    builder.setNegativeButton("Capture",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    captureScreen();
                    Context context = getApplicationContext();
                    Toast.makeText(context, "Screenshot Captured", Toast.LENGTH_LONG).show();
                }
            });

    builder.setNeutralButton("Return", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
        }
    });
    builder.show();
}

进一步编辑:

这里你将看到两张截图,第一张展示了当从对话框中保存所有内容的截图时,你会注意到底部总是有一些文本。

Screenshot1

第二张屏幕截图是当对话框中有大量文本时,对话框是可滚动的,这样您就可以查看所有数据,您会注意到第一个屏幕截图中的底部字符串不存在。

Screenshot2

如果可能的话,我希望所有的数据都能显示出来。但我不确定是截屏功能可以做到这一点,还是需要其他方法。

请发布您的对话框代码。 - Rohit5k2
你只需要对话框的截图吗?因为我刚刚开发了一个相关代码。 - Rohit5k2
这很有趣:开发一个代码来回答一个问题。 :D - Rohit5k2
3个回答

8

使用Android 5模拟器开发并且能够正常运行。从您提供的链接中获取了您的对话框代码和屏幕截图代码。

这是您的AlertDialog

public void showCalc(String title, String message) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setCancelable(true);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.setPositiveButton("Capture + Open",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    //Remove Values From Inventory
                    captureScreenAndOpen();
                }
            });

    builder.setNegativeButton("Capture",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    AlertDialog dialog2 =AlertDialog.class.cast(dialog);
                    takeScreenshot(dialog2);
                    Context context = getApplicationContext();
                    Toast.makeText(context, "Screenshot Captured", Toast.LENGTH_LONG).show();
                }
            });

    builder.setNeutralButton("Return", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
        }
    });
    builder.show();
}

这是截图代码。
private void takeScreenshot(AlertDialog dialog) {
    Date now = new Date();
    android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);

    try {
        // image naming and path  to include sd card  appending name you choose for file
        String mPath = "/data/data/com.rohit.test/test.jpg"; // use your desired path

        // create bitmap screen capture
        View v1 = dialog.getWindow().getDecorView().getRootView();

        v1.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        File imageFile = new File(mPath);

        FileOutputStream outputStream = new FileOutputStream(imageFile);
        int quality = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
        outputStream.flush();
        outputStream.close();

    } catch (Throwable e) {
        // Several error may come out with file handling or OOM
        e.printStackTrace();
    }
}

已截图

在此输入图片描述

提示1:如果你将参数类型更改为 View 并将 dialog.getWindow().getDecorView().getRootView(); 移动到从调用此方法的对话框代码中,则可以概括方法 takeScreenshot

提示2:看到你更新了问题。当其中一些内容被隐藏时,我认为无法在截图中获得所有数据。可以将其类比为正常的截屏(在计算机或甚至手机上)。只拍摄可见的内容。


谢谢,现在这段代码运行得很好,差不多就是... 有时消息框能够滚动以适应所有内容,这可能有点过于保守,但你知道有没有一种方法可以保存对话框中的所有内容而不仅仅是可见内容? - Sjharrison
我在这段代码中使用的视图是完整对话框。因此,对话框上的任何内容都将被捕获。 - Rohit5k2
@Sjharrison:看到你更新了问题。我认为当一些数据被隐藏时,你无法在截图中获取全部数据。就像普通的截图一样,你只能拍摄到你能看到的部分。 - Rohit5k2
我认为那应该是答案,我能想到的唯一替代方案是当他们按下“捕获”时,它会截屏,然后保留对话框而不是关闭它,但是我能想到的唯一方法是重新调用代码? - Sjharrison
我猜那可能是唯一的解决方案,但老实说我不确定。也许你可以针对这个特定的问题发布另一个问题。我相信会有人确认或者给出解决方案。 - Rohit5k2
1
我找到了一篇关于防止对话框消失的帖子,所以会使用它,非常感谢您对此的帮助,很高兴您为我创建了解决方案 :) - Sjharrison

3

1

1. 亲爱的朋友,您做错了一件事情,导致您无法截取对话框的屏幕截图。

View v1 = getWindow().getDecorView().getRootView();

你正在捕获位于AlertDialog下方的整个屏幕。你可以通过将对话框视图发送到此方法来完成以下操作:

从视图获取位图

    public static Bitmap loadView(View v) {
    Bitmap b = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    v.layout(0, 0, v.getWidth(), v.getHeight());
    v.draw(c);
    return b;
}

保存您的位图
    void saveFile(Bitmap bitmap) {
    String extr = Environment.getExternalStorageDirectory().toString() +   File.separator + "Folder";
    String fileName = new SimpleDateFormat("yyyyMMddhhmm'_bitmap.jpg'", Locale.US).format(new Date());
    File myPath = new File(extr, fileName);
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(myPath);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
        MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Screen", "screen");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我已经根据您的建议更改了我的代码,但是在我的对话框中,我调用方法时它们要求传入参数,您有什么想法这些参数应该是什么? - Sjharrison
@Sjharrison,你在谈论什么类型的参数?能否提供一下你的示例代码? - Harsh Sharma
如果您查看我上面的对话框代码,您会发现我基本上创建了一个新的对话框 'sendDialogToView();',它是您的 '从视图获取位图' 代码,而 'captureScreenAndOpen();' 则是您的保存位图代码。 - Sjharrison
@Sjharrison,你只需要将AlertDialog视图传递给loadView()方法,它会返回一个位图,然后将该位图传递给saveFile()方法即可。记得从参数中删除高度和宽度。 - Harsh Sharma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接