title: Android - Display a screen recording on a SurfaceView
body: <p>I am developing an application that can record the contents of an Android device's screen and display it on a SurfaceView. As of now, the SurfaceView is a box in the middle of the screen and is currently showing the contents of the entire screen, along with itself, creating a repeating image. Is there a way to repeatedly hide the SurfaceView, create a virtual display, then show the SurfaceView with the contents of the virtual display?</p>
  <p><strong>RecordingSession.java</strong></p>
  <pre><code>class RecordingSession
    implements MediaScannerConnection.OnScanCompletedListener {
    static final int VIRT_DISPLAY_FLAGS=
      DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
        DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
    private RecordingConfig config;
    private final File output;
    private final Context ctxt;
    private final ToneGenerator beeper;
    private MediaRecorder recorder;
    private MediaProjection projection;
    private VirtualDisplay vdisplay;
    private Window window;
  
    RecordingSession(Context ctxt, RecordingConfig config,
                     MediaProjection projection, Window window) {
      this.ctxt=ctxt.getApplicationContext();
      this.window = window;
      this.config=config;
      this.projection=projection;
      this.beeper=new ToneGenerator(
        AudioManager.STREAM_NOTIFICATION, 100);
  
      output=new File(ctxt.getExternalFilesDir(null), &quot;andcorder.mp4&quot;);
      output.getParentFile().mkdirs();
    }
  
    void start() {
  
        //this.window.close();
      vdisplay=projection.createVirtualDisplay(&quot;andcorder&quot;,
              config.width, config.height, config.density,
              VIRT_DISPLAY_FLAGS, this.window.getScreenShot().getHolder().getSurface(), null, null);
      //this.window.open();
      beeper.startTone(ToneGenerator.TONE_PROP_ACK);
    }
  
    void stop() {
      projection.stop();
      vdisplay.release();
    }
  
    @Override
    public void onScanCompleted(String path, Uri uri) {
      beeper.startTone(ToneGenerator.TONE_PROP_NACK);
    }
  }
  </code></pre>
  <p><strong>Window.java</strong></p>
  <pre><code>public class Window {
  
      // declaring required variables
      private Context context;
      private View mView;
      private WindowManager.LayoutParams mParams;
      private WindowManager mWindowManager;
      private LayoutInflater layoutInflater;
  
      public SurfaceView getScreenShot() {
          return screenShot;
      }
  
      private SurfaceView screenShot;
      private LinearLayout toDisplay;
  
      public Window(Context context){
          this.context=context;
  
          if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {
              // set the layout parameters of the window
              mParams = new WindowManager.LayoutParams(
                      // Shrink the window to wrap the content rather
                      // than filling the screen
                      WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
                      // Display it on top of other application windows
                      WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                      // Don't let it grab the input focus
                      WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                      // Make the underlying application window visible
                      // through any transparent parts
                      PixelFormat.TRANSLUCENT);
  
          }
          // getting a LayoutInflater
          layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          // inflating the view with the custom layout we created
          mView = layoutInflater.inflate(R.layout.popup_window, null);
          screenShot= mView.findViewById(R.id.screenShot);
          
          // Define the position of the
          // window within the screen
          mParams.gravity = Gravity.CENTER;
          mWindowManager = (WindowManager)context.getSystemService(WINDOW_SERVICE);
      }
  
      public void open() {
  
          try {
              // check if the view is already
              // inflated or present in the window
              if(mView.getWindowToken()==null) {
                  if(mView.getParent()==null) {
                      mWindowManager.addView(mView, mParams);
                  }
              }
          } catch (Exception e) {
              Log.d(&quot;Error1&quot;,e.toString());
          }
  
      }
  
      public void hide() {
          try {
              mView.setVisibility(View.INVISIBLE);
          } catch (Exception e) {
              Log.d(&quot;Error3&quot;,e.toString());
          }
      }
  
      public void show() {
          try {
              mView.setVisibility(View.VISIBLE);
          } catch (Exception e) {
              Log.d(&quot;Error4&quot;,e.toString());
          }
      }
  
      public void close() {
  
          try {
              // remove the view from the window
              ((WindowManager)context.getSystemService(WINDOW_SERVICE)).removeView(mView);
              // invalidate the view
              mView.invalidate();
              // remove all views
              ((ViewGroup)mView.getParent()).removeAllViews();
  
              // the above steps are necessary when you are adding and removing
              // the view simultaneously, it might give some exceptions
          } catch (Exception e) {
              Log.d(&quot;Error2&quot;,e.toString());
          }
      }
  }
  </code></pre>
  <p><strong>popup_window.xml</strong></p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;RelativeLayout
      xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      android:layout_width=&quot;wrap_content&quot;
      android:layout_height=&quot;wrap_content&quot;
      xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
      android:padding=&quot;4dp&quot;
      android:background=&quot;@null&quot;&gt;
  
          &lt;SurfaceView
              android:id=&quot;@+id/screenShot&quot;
              android:layout_width=&quot;match_parent&quot;
              android:layout_height=&quot;250dp&quot; /&gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>