Как записывать экран и делать скриншоты с помощью Android API?

Фон

Android получил новый API на Kitkat и Lollipop для захвата видео с экрана. Вы можете сделать это либо с помощью инструмента ADB, либо с помощью кода (начиная с Lollipop).

С тех пор как появился новый API, многие приложения использовали эту функцию, позволяющую записывать экран, и Microsoft даже создала собственное приложение-конкурент Google-Now-On-Tap.

Используя ADB, вы можете использовать:

adb shell screenrecord /sdcard/video.mp4 

Вы даже можете сделать это из самой Android Studio.

Проблема

Я не могу найти учебник или объяснение того, как это сделать с помощью API, то есть в коде.

Что я нашел

Единственное место, которое я нашел, - это документация (здесь, в разделе "Снимок экрана и совместное использование"), где говорится:

Android 5.0 позволяет добавлять захват экрана и совместное использование экрана возможности вашего приложения с новыми API-интерфейсами android.media.projection. Эта функция полезна, например, если вы хотите включить совместное использование экрана в приложении для видеоконференций.

Новый метод createVirtualDisplay() позволяет вашему приложению захватывать содержимое основного экрана (дисплей по умолчанию) в поверхность объект, который ваше приложение может затем отправить по сети. Только API позволяет захватывать незащищенный контент экрана, а не системный звук. к начать захват экрана, ваше приложение должно сначала запросить пользователей разрешение путем запуска диалога захвата экрана с помощью намерения получено с помощью метода createScreenCaptureIntent().

Пример использования новых API приведен в MediaProjectionDemo. класс в примере проекта.

Дело в том, что я не могу найти образец "MediaProjectionDemo". Вместо этого я нашел образец "Захват экрана", но я не понимаю, как он работает. Когда я его запускаю, я вижу только мигающий экран и не думаю, что он сохраняет видео в файл. Образец кажется очень глючным.

Вопросы

Как мне выполнить эти действия, используя новый API:

  1. начать запись, опционально включая звук (микрофон/динамик/оба).
  2. остановить запись
  3. сделать скриншот вместо видео.

Кроме того, как я могу настроить его (разрешение, запрашиваемые кадры в секунду, цвета, время...)?

Ответ 1

Первый шаг и тот, который Кен Уайт справедливо предложил & Пример кода, предоставленный вами официально.

Я использовал их API ранее. Я согласен, скриншот довольно прост. Но запись экрана также находится под похожими чертами.

Я отвечу на ваши вопросы в 3 разделах и заверну их ссылкой. :)


1. Начните запись видео

private void startScreenRecord(final Intent intent) {
 if (DEBUG) Log.v(TAG, "startScreenRecord:sMuxer=" + sMuxer);
 synchronized(sSync) {
  if (sMuxer == null) {
   final int resultCode = intent.getIntExtra(EXTRA_RESULT_CODE, 0);
   // get MediaProjection 
   final MediaProjection projection = mMediaProjectionManager.getMediaProjection(resultCode, intent);
   if (projection != null) {
    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    final int density = metrics.densityDpi;

    if (DEBUG) Log.v(TAG, "startRecording:");
    try {
     sMuxer = new MediaMuxerWrapper(".mp4"); // if you record audio only, ".m4a" is also OK. 
     if (true) {
      // for screen capturing 
      new MediaScreenEncoder(sMuxer, mMediaEncoderListener,
       projection, metrics.widthPixels, metrics.heightPixels, density);
     }
     if (true) {
      // for audio capturing 
      new MediaAudioEncoder(sMuxer, mMediaEncoderListener);
     }
     sMuxer.prepare();
     sMuxer.startRecording();
    } catch (final IOException e) {
     Log.e(TAG, "startScreenRecord:", e);
    }
   }
  }
 }
}

2. Остановить запись видео

 private void stopScreenRecord() {
  if (DEBUG) Log.v(TAG, "stopScreenRecord:sMuxer=" + sMuxer);
  synchronized(sSync) {
   if (sMuxer != null) {
    sMuxer.stopRecording();
    sMuxer = null;
    // you should not wait here 
   }
  }
 }

2.5. Приостановить и возобновить запись видео

 private void pauseScreenRecord() {
  synchronized(sSync) {
   if (sMuxer != null) {
    sMuxer.pauseRecording();
   }
  }
 }

 private void resumeScreenRecord() {
  synchronized(sSync) {
   if (sMuxer != null) {
    sMuxer.resumeRecording();
   }
  }
 }

Надеюсь, код поможет. Вот оригинальная ссылка на код, на который я ссылался и откуда взята эта реализация (Запись видео).


3. Сделайте скриншот вместо видео

Я думаю, что по умолчанию легко захватить изображение в растровом формате. Вы все еще можете воспользоваться примером MediaProjectionDemo, чтобы сделать снимок экрана.

[EDIT]: шифрование кода для скриншота

а. Для создания виртуального дисплея в зависимости от ширины/высоты устройства

mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);
mVirtualDisplay = sMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight, mDensity, VIRTUAL_DISPLAY_FLAGS, mImageReader.getSurface(), null, mHandler);
mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler);

б. Затем запустите захват экрана на основе намерения или action-

startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);

Stop Media projection-

sMediaProjection.stop();

с. Затем конвертируйте в image-

//Process the media capture
image = mImageReader.acquireLatestImage();
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
//Create bitmap
bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
//Write Bitmap to file in some path on the phone
fos = new FileOutputStream(STORE_DIRECTORY + "/myscreen_" + IMAGES_PRODUCED + ".png");
bitmap.compress(CompressFormat.PNG, 100, fos);
fos.close();

Существует несколько реализаций (полный код) API Media Projection. Некоторые другие ссылки, которые могут помочь вам в вашем development-

  1. Запись видео с MediaProjectionManager - веб-сайт

  2. android-ScreenCapture - github согласно наблюдениям разработчиков Android :)

  3. скриншот - github

  4. Захват и запись экрана Android с помощью API MediaProjection - веб-сайт


Надеюсь, это поможет :) Удачного кодирования и записи экрана!

PS: Скажите, пожалуйста, о приложении Microsoft, о котором вы говорите? Я не использовал это. Хотел бы попробовать :)