How to take a screenshot of Android's Surface View?

12,753

Solution 1

The code from the Usman Kurd answer will not work is most cases.

Unless you're rendering H.264 video frames in software with Canvas onto a View, the drawing-cache approach won't work (see e.g. this answer).

You cannot read pixels from the Surface part of the SurfaceView. The basic problem is that a Surface is a queue of buffers with a producer-consumer interface, and your app is on the producer side. The consumer, usually the system compositor (SurfaceFlinger), is able to capture a screen shot because it's on the other end of the pipe.

Take Screenshot of SurfaceView

Solution 2

I hope this also useful for you. here little difference for the above answer is for I used glsurfaceview to take the screen shots hen i click the button. this image is stored in sdcard for mentioned folder : sdcard/emulated/0/printerscreenshots/image/...images

 My Program :

 View view_storelayout ;
 view_storelayout = findViewById(R.id.gl_surface_view);

   button onclick() {

   view_storelayout.setDrawingCacheEnabled(true); 

view_storelayout.buildDrawingCache(true);

Bitmap bmp = Bitmap.createBitmap(view_storelayout.getDrawingCache());
view_storelayout.setDrawingCacheEnabled(false); // clear drawing cache
                ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
                bmp.compress(CompressFormat.JPEG, 90, bos); 
                byte[] bitmapdata = bos.toByteArray();
                ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata);

                final Calendar c=Calendar.getInstance();
                 long mytimestamp=c.getTimeInMillis();
                String timeStamp=String.valueOf(mytimestamp);
                String myfile="hari"+timeStamp+".jpeg";

 dir_image=new  File(Environment.getExternalStorageDirectory()+
      File.separator+"printerscreenshots"+File.separator+"image");
                dir_image.mkdirs();

                try {
                    File tmpFile = new File(dir_image,myfile); 
                    FileOutputStream fos = new FileOutputStream(tmpFile);

                     byte[] buf = new byte[1024];
                        int len;
                        while ((len = fis.read(buf)) > 0) {
                            fos.write(buf, 0, len);
                        }
                            fis.close();
                            fos.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

     Toast.makeText(getApplicationContext(), "myPath:"
            +dir_image.toString(), Toast.LENGTH_SHORT).show();
                Log.v("hari", "screenshots:"+dir_image.toString());

  }

 Note :
          But, here i am faced one problem. In this surfaceview , i drawn line and circle
  at runtime. after drawn some objects, when i take screenshots , its stored only for
  black image like surfaceview is stored as an image.

 And also i want to store that surfaceview image as an .dxf format(autocad format).
 i tried to stored image file as an .dxf file format.its saved successfully in 
 autocad format. but, it cant open in autocad software to edit my .dxf file.
Share:
12,753
Tariq Mahmood
Author by

Tariq Mahmood

Updated on July 26, 2022

Comments

  • Tariq Mahmood
    Tariq Mahmood almost 2 years

    I want to programatically take screen shot of my game, just as you'd get in Eclipse DDMS.

    Screenshot taken through the solution proposed here: How to programmatically take a screenshot in Android? and in most other SO questions only have View elements visible, but not the SurfaceView.

    SCREENSHOTS_LOCATIONS = Environment.getExternalStorageDirectory().toString() + "/screenshots/";
    // Get root view
    View view = activity.getWindow().getDecorView().getRootView();
    // Create the bitmap to use to draw the screenshot
    final Bitmap bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
    final Canvas canvas = new Canvas(bitmap);
    
    // Get current theme to know which background to use
    final Theme theme = activity.getTheme();
    final TypedArray ta = theme
        .obtainStyledAttributes(new int[] { android.R.attr.windowBackground });
    final int res = ta.getResourceId(0, 0);
    final Drawable background = activity.getResources().getDrawable(res);
    
    // Draw background
    background.draw(canvas);
    
    // Draw views
    view.draw(canvas);
    
    // Save the screenshot to the file system
    FileOutputStream fos = null;
    try {
        final File sddir = new File(SCREENSHOTS_LOCATIONS);
        if (!sddir.exists()) {
            sddir.mkdirs();
        }
        fos = new FileOutputStream(SCREENSHOTS_LOCATIONS
                + System.currentTimeMillis() + ".jpg");
        if (fos != null) {
            if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)) {
                Log.d("ScreenShot", "Compress/Write failed");
            }
            fos.flush();
            fos.close();
        }
    
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    

    Any help in this regard would be highly appreciated. Thanks.