title: Android - Screen Share using Agora.io
body: <p>I am trying to implement <strong>Screen Share</strong> using <strong>Agora.io</strong> on Android. I tried to follow their demo however the solution using low level Android graphics API seems a bit too complex so I tried using ImageReader for this.</p>
  
  <p>from my activity I create a service (<strong>ShareScreenService</strong> inheriting from Service)</p>
  
  <p>to start screensharing there I do following</p>
  
  <pre><code>private void StartScreenShare(int resultCode, Intent resultData)
          {
              var mediaProjectionManager = (MediaProjectionManager)GetSystemService(MediaProjectionService);
              var mediaProjection = mediaProjectionManager.GetMediaProjection(resultCode, resultData);
              _shareScreenImageAvailableListener = new ShareScreenImageAvailableListener(this);
              var virtualDisplay = mediaProjection.CreateVirtualDisplay("sharescreen", Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels, (int)Resources.DisplayMetrics.DensityDpi, DisplayFlags.SupportsProtectedBuffers | DisplayFlags.Presentation, _shareScreenImageAvailableListener.Surface, null, _handler);
              var mediaProjectionCallback = new MediaProjectionCallback(virtualDisplay);
              mediaProjection.RegisterCallback(mediaProjectionCallback, _handler);
  
              AgoraVideoService.Instance.StartScreenShare();
          }
  
  AgoraVideoService.Instance.StartScreenShare does following:
  
  internal void StartScreenShare()
          {
              _agoraEngine.SetExternalVideoSource(true, false, true);
          }
  </code></pre>
  
  <p>my <strong>ShareScreenImageAvailableListener</strong> looks like this:</p>
  
  <pre><code>public class ShareScreenImageAvailableListener : Java.Lang.Object, ImageReader.IOnImageAvailableListener
      {
          private ScreenShareService _screenShareService;
          private ImageReader _imageReader;
  
          public Surface Surface
          {
              get
              {
                  return _imageReader.Surface;
              }
          }
  
          public ShareScreenImageAvailableListener(ScreenShareService screenShareService)
          {
              _screenShareService = screenShareService;
              _imageReader = ImageReader.NewInstance(_screenShareService.Width, _screenShareService.Height, Android.Graphics.ImageFormatType.Jpeg, 1);
              _imageReader.SetOnImageAvailableListener(this, _screenShareService.Handler);
          }
  
          public void OnImageAvailable(ImageReader reader)
          {
              using (var image = reader.AcquireLatestImage())
              {
                  using (var planes = image.GetPlanes()[0])
                  {
                      using (var buffer = planes.Buffer)
                      {
                          byte[] bytes = new byte[buffer.Capacity()];
                          buffer.Get(bytes);
  
                          _screenShareService.ShareScreenImage(bytes, image.Height, image.Format, planes.PixelStride);
                      }
                  }
                  image.Close();
              }
          }
      }
  </code></pre>
  
  <p>then when sharing the <strong>ShareScreenImage</strong>:</p>
  
  <pre><code>internal void ShareScreenImage(byte[] bytes, int height, ImageFormatType format, int pixelStride)
          {
              var agoraVideoFrame = new AgoraVideoFrame()
              {
                  Buf = bytes,
                  Height = height,
                  Format = (int)format,
                  Stride = pixelStride,
                  TimeStamp = DateTime.UtcNow.Ticks,
                 CropBottom = 0,
                 CropLeft = 0,
                 CropRight = 0,
                 CropTop = 0
              };
  
              AgoraVideoService.Instance.ShareExternalVideoFrame(agoraVideoFrame);
          }
  </code></pre>
  
  <p>and lastly <strong>ShareExternalVideoFrame</strong> looks like this:</p>
  
  <pre><code>_agoraEngine.PushExternalVideoFrame(agoraVideoFrame);
  </code></pre>
  
  <p><strong>Finally, my question: is my thinking correct in terms of implementing this? Can I use ImageReader or do I need to go lower to start using EglCore etc. from Agora demo implementation?</strong></p>
  
  <p>I can verify that OnImageAvailable is being called (multiple times until I stop it) <strong>PushExternalVideoFrame</strong> returns "true" which looks like the frames get pushed successfully</p>
  
  <p>However this doesn't produce any results, I cannot see the screen being shared. So I would at least verify that this is a possible solution. </p>