title: Take a screenshot using MediaProjection
body: <p>With the <code>MediaProjection</code> APIs available in Android L it's possible to </p>
  
  <blockquote>
    <p>capture the contents of the main screen (the default display) into a Surface object, which your app can then send across the network</p>
  </blockquote>
  
  <p>I have managed to get the <code>VirtualDisplay</code> working, and my <code>SurfaceView</code> is correctly displaying the content of the screen. </p>
  
  <p>What I want to do is to capture a frame displayed in the <code>Surface</code>, and print it to file. I have tried the following, but all I get is a black file:</p>
  
  <pre><code>Bitmap bitmap = Bitmap.createBitmap
      (surfaceView.getWidth(), surfaceView.getHeight(), Bitmap.Config.ARGB_8888);
  Canvas canvas = new Canvas(bitmap);
  surfaceView.draw(canvas);
  printBitmapToFile(bitmap);
  </code></pre>
  
  <p>Any idea on how to retrieve the displayed data from the <code>Surface</code>?</p>
  
  <h2>EDIT</h2>
  
  <p>So as @j__m suggested I'm now setting up the <code>VirtualDisplay</code> using the <code>Surface</code> of an <code>ImageReader</code>:</p>
  
  <pre><code>Display display = getWindowManager().getDefaultDisplay();
  Point size = new Point();
  display.getSize(size);
  displayWidth = size.x;
  displayHeight = size.y;
  
  imageReader = ImageReader.newInstance(displayWidth, displayHeight, ImageFormat.JPEG, 5);
  </code></pre>
  
  <p>Then I create the virtual display passing the <code>Surface</code> to the <code>MediaProjection</code>:</p>
  
  <pre><code>int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
  
  DisplayMetrics metrics = getResources().getDisplayMetrics();
  int density = metrics.densityDpi;
  
  mediaProjection.createVirtualDisplay("test", displayWidth, displayHeight, density, flags, 
        imageReader.getSurface(), null, projectionHandler);
  </code></pre>
  
  <p>Finally, in order to get a "screenshot" I acquire an <code>Image</code> from the <code>ImageReader</code> and read the data from it:</p>
  
  <pre><code>Image image = imageReader.acquireLatestImage();
  byte[] data = getDataFromImage(image);
  Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
  </code></pre>
  
  <p><strong>The problem is that the resulting bitmap is <code>null</code>.</strong></p>
  
  <p>This is the <code>getDataFromImage</code> method:</p>
  
  <pre><code>public static byte[] getDataFromImage(Image image) {
     Image.Plane[] planes = image.getPlanes();
     ByteBuffer buffer = planes[0].getBuffer();
     byte[] data = new byte[buffer.capacity()];
     buffer.get(data);
  
     return data;
  }
  </code></pre>
  
  <p><strong>The <code>Image</code> returned from the <code>acquireLatestImage</code> has always data with default size of 7672320 and the decoding returns <code>null</code>.</strong></p>
  
  <p>More specifically, when the <code>ImageReader</code> tries to acquire an image, the status <code>ACQUIRE_NO_BUFS</code> is returned.</p>