0

I am using the HelloAR demo application and I am trying to take a screenshot of the entire screen (menu bar and everything). I am able to take a screenshot, but not everything is captured... GUI elements are visible in the screenshot, but the camera feed is not.

Here is my code:

int counter = 0;
private void takeScreenShot()
{
    View view = getWindow().getDecorView().getRootView();
    Bitmap bmp = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
    PixelCopy.request(getWindow(), bmp, copyResult -> {
        if(copyResult == PixelCopy.SUCCESS){
            String filename = getExternalFilesDir(null) + File.separator + "SCREENSHOTS" + File.seperator + "SS_" + counter + ".png";
            store(bmp, filename);
            counter++;
        }
    }, new Handler());
}

public static void storeit(Bitmap bm, String fileName){
    File file = new File(fileName);
    try {
        FileOutputStream fOut = new FileOutputStream(file);
        bm.compress(Bitmap.CompressFormat.PNG, 85, fOut);
        fOut.flush();
        fOut.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

And here is what the screenshot looks like:

enter image description here

How can I capture the entire screen (camera feed, UI elements, menu bar, etc.)?

pookie
  • 3,796
  • 6
  • 49
  • 105

1 Answers1

0

You could use MediaProjection to capture the screen contents. This has the drawback of requesting the user for screen sharing permission. (Reference SO answer with example)

Alternatively, you could get the content of the GLSurfaceView using glReadPixels fn & superimpose your existing View image over it. (Reference SO answer with example)


The reason your current implementation doesn't work is because

SurfaceView and GLSurfaceView punch holes in their windows to allow their surfaces to be displayed (Android src reference). In other words, they have transparent areas. So you cannot capture an image by calling GLSurfaceView.getDrawingCache().

If you want to get an image from GLSurfaceView, you should invoke glReadPixels() in GLSurfaceView.onDrawFrame().

Chrisvin Jem
  • 3,940
  • 1
  • 8
  • 24
  • Thanks, but any idea why the approach I am taking does not work? Why are only some of the contents captured? – pookie Aug 10 '20 at 23:19
  • Basically, `GLSurfaceView` doesn't draw its own contents, it literally has an empty space which is rendered into by the `GLSurfaceView.Renderer`. Take a look at the links I've shared in my edited answer. – Chrisvin Jem Aug 11 '20 at 00:47
  • Thanks, that is more clear. However, if I capture the GLSurfaceView, then will that include the UI elements and the top menu bar? – pookie Aug 11 '20 at 11:51
  • If by capture, you mean the `glReadPixels()` , then No. You'll only get the content being displayed in the `GLSurfaceView` , but you should be able to superimpose your existing image (generated using `PixelCopy`) on the surface view image to get your required image. – Chrisvin Jem Aug 12 '20 at 19:33
  • Superimposing should be fairly simple (assuming width & height are the same), create a new bitmap, use `Canvas.drawBitmap()` to draw the old images in the new bitmap. ([Example](https://stackoverflow.com/a/41221134/11016588)) – Chrisvin Jem Aug 12 '20 at 19:40