title: Cannot start already started MediaProjection and rarely NullPointerException when invoking MediaProjection.createVirtualDisplay
body: <p>These are the errors I am getting:</p>
  <pre><code>2021-10-31 12:18:44.281 15783-15921/com.exabes.test E/AndroidRuntime: FATAL EXCEPTION: Thread-7
      Process: com.exabes.test, PID: 15783
      java.lang.IllegalStateException: Cannot start already started MediaProjection
          at android.os.Parcel.createException(Parcel.java:1974)
          at android.os.Parcel.readException(Parcel.java:1934)
          at android.os.Parcel.readException(Parcel.java:1884)
          at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:144)
          at android.media.projection.MediaProjection.&lt;init&gt;(MediaProjection.java:69)
          at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:169)
          at com.autobot.service.AbstractNotificationService.startCapture(AbstractNotificationService.java:241)
          at com.exabes.test.ExampleThread.run(ExampleThread.java:813)
       Caused by: android.os.RemoteException: Remote stack trace:
          at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:416)
          at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:52)
          at android.os.Binder.execTransact(Binder.java:739)
  </code></pre>
  <p>and:</p>
  <pre><code>2021-10-31 12:35:40.293 17831-17992/com.exabes.test E/AndroidRuntime: FATAL EXCEPTION: Thread-7
      Process: com.exabes.test, PID: 17831
      java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.display.VirtualDisplay android.media.projection.MediaProjection.createVirtualDisplay(java.lang.String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay$Callback, android.os.Handler)' on a null object reference
          at com.exabes.test.AbstractNotificationService.startCapture(AbstractNotificationService.java:251)
          at com.exabes.test.ExampleThread.run(ExampleThread.java:813)
  </code></pre>
  <p>I am basically requesting the <code>createScreenCaptureIntent</code> in the MainActivity and pass the results to the AccessebilityService where all the methods necessary to take a screenshots are declared. Then I simply call <code>startCapture()</code> into the Thread.
  I am gonna post most of the code.</p>
  <p>MainActivity:</p>
  <pre><code>public class MainActivity extends Activity {
  
  private static final int DRAW_OVER_OTHER_APP_PERMISSION = 123;
  
  private static final int REQUEST_SCREENSHOT=59706;
  private MediaProjectionManager mgr;
  
  int resultCodeX;
  Intent dataX;
  
  
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); //TODO
  
      mgr=(MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
      startActivityForResult(mgr.createScreenCaptureIntent(), REQUEST_SCREENSHOT);
  
      this.askPermissions();
  
      ...
  }
  
  
  public void startService()
  {
          // To prevent starting the service if the required permission is NOT granted.
          if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.M || Settings.canDrawOverlays(MainActivity.this)) {
              Intent intent = new Intent(MainActivity.this, ExampleService.class);
              intent.putExtra(getString(R.string.edit_text_name), Objects.requireNonNull(trainerUsernameEditText.getText()).toString());
              intent.putExtra(ExampleService.EXTRA_RESULT_CODE, resultCodeX);
              intent.putExtra(ExampleService.EXTRA_RESULT_INTENT, dataX);
              if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O)
                  startForegroundService(intent);
              else
                  startService(intent);
              finish();
          } else {
              error();
              askForSystemOverlayPermission();
          }
  }
  
  
  
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  
      if (requestCode == REQUEST_SCREENSHOT) {
          if (resultCode == RESULT_OK) {
              //TODO
              resultCodeX=resultCode;
              dataX=data;
              //finish();
          }
      }
  
      else if (requestCode == DRAW_OVER_OTHER_APP_PERMISSION) {
  
          if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {
              if (!Settings.canDrawOverlays(this)) {
                  //Permission is not available. Display error text.
                  errorToast();
                  finish();
              }
          }
      }
  
      else {
          super.onActivityResult(requestCode, resultCode, data);
      }
  }}
  </code></pre>
  <p>AccesibilityService:</p>
  <pre><code>public abstract class AbstractNotificationService extends AccessibilityService {
  
  private static final String ACTION_STOP = &quot;STOP&quot;;
  private NotificationCompat.Builder builder;
  private NotificationManagerCompat notificationManager;
  
  private ActivityManager activityManager;
  
  
  private static final String CHANNEL_WHATEVER=&quot;channel_whatever&quot;;
  private static final int NOTIFY_ID=9906;
  public static final String EXTRA_RESULT_CODE=&quot;resultCode&quot;;
  public static final String EXTRA_RESULT_INTENT=&quot;resultIntent&quot;;
  static final String ACTION_RECORD=
          BuildConfig.APPLICATION_ID+&quot;.RECORD&quot;;
  static final String ACTION_SHUTDOWN=
          BuildConfig.APPLICATION_ID+&quot;.SHUTDOWN&quot;;
  static final int VIRT_DISPLAY_FLAGS=
          DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
                  DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
  private MediaProjection projection;
  private VirtualDisplay vdisplay;
  final private HandlerThread handlerThread=
          new HandlerThread(getClass().getSimpleName(),
                  android.os.Process.THREAD_PRIORITY_BACKGROUND);
  private Handler handler;
  private MediaProjectionManager mgr;
  private WindowManager wmgr;
  private ImageTransmogrifier it;
  private int resultCode;
  private Intent resultData;
  final private ToneGenerator beeper=
          new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
  
  
  
  @Override
  public void onCreate() {
      super.onCreate();
  
      activityManager = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
  
  
      mgr=(MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
      wmgr=(WindowManager)getSystemService(WINDOW_SERVICE);
  
      handlerThread.start();
      handler=new Handler(handlerThread.getLooper());
  }
  
  
  
  @Override
  public int onStartCommand (Intent intent, int flags, int startId) {
  
      String action = intent.getAction();
      if (action != null) {
          if (action.equals(getString(R.string.stop_foreground_action))) {
              stopForeground(true);
              stopSelf();
  
              return START_NOT_STICKY;
          }
      }
      else {
          resultCode=intent.getIntExtra(EXTRA_RESULT_CODE, 1337);
          resultData=intent.getParcelableExtra(EXTRA_RESULT_INTENT);
          //foregroundify();
      }
  
      //return START_STICKY;
      return START_REDELIVER_INTENT;
  }
  
  
  @Override
  public void onDestroy() {
      super.onDestroy();
  
      //TODO
      beeper.startTone(ToneGenerator.TONE_PROP_NACK);
      stopCapture();
  }
  
  
  public abstract void sendNotification(String response);
  
  
  public void killBackground(String packageName)
  {
      activityManager.killBackgroundProcesses(packageName);
  }
  
  
  
  public WindowManager getWindowManager() {
      return(wmgr);
  }
  
  public Handler getHandler() {
      return(handler);
  }
  
  public void processImage(final byte[] png) {
      new Thread() {
          @Override
          public void run() {
              //File output=new File(getExternalFilesDir(null),&quot;screenshot.png&quot;);
              File output=new File(Environment.getExternalStorageDirectory(),&quot;screenshot.png&quot;);
  
              try {
                  FileOutputStream fos=new FileOutputStream(output);
  
                  fos.write(png);
                  fos.flush();
                  //fos.getFD().sync();
                  fos.close();
  
                  MediaScannerConnection.scanFile(AbstractNotificationService.this,
                          new String[] {output.getAbsolutePath()},
                          new String[] {&quot;image/png&quot;},
                          null);
              }
              catch (Exception e) {
                  Log.e(getClass().getSimpleName(), &quot;Exception writing out screenshot&quot;, e);
              }
          }
      }.start();
  
      beeper.startTone(ToneGenerator.TONE_PROP_ACK);
      stopCapture();
  }
  
  private void stopCapture() {
      if (projection!=null) {
          projection.stop();
          vdisplay.release();
          projection=null;
      }
  }
  
  public void startCapture() {
      projection=mgr.getMediaProjection(resultCode, resultData);
      it=new ImageTransmogrifier(this);
  
      MediaProjection.Callback cb=new MediaProjection.Callback() {
          @Override
          public void onStop() {
              vdisplay.release();
          }
      };
  
      vdisplay=projection.createVirtualDisplay(&quot;andshooter&quot;,
              it.getWidth(), it.getHeight(),
              getResources().getDisplayMetrics().densityDpi,
              VIRT_DISPLAY_FLAGS, it.getSurface(), null, handler);
      projection.registerCallback(cb, handler);
  }}
  </code></pre>
  <p>Thread:</p>
  <pre><code>public class ExampleThread extends Thread {
  
  private AbstractNotificationService notificationService;
  
  
  public ExampleThread(AbstractNotificationService notificationService)
  {
      this.notificationService = notificationService;
  }
  
  
  @Override
  public void run()
  {
      
      while(boolean){
          ...
          notificationService.startCapture();
      }
      notificationService.sendNotification(&quot;ENDED&quot;);
  }}
  </code></pre>