如何使用Android API记录屏幕并截取屏幕截图?

and*_*per 40 android screenshot screen-recording android-4.4-kitkat android-5.0-lollipop

背景

Android在Kitkat和Lollipop上获得了新的API,用于视频捕获屏幕.您可以通过ADB工具或通过代码(从Lollipop开始)来完成.

自新API发布以来,许多应用程序都使用此功能,允许记录屏幕,微软甚至制作了自己的Google-Now-On-tap竞争对手应用程序.

使用ADB,您可以使用:

adb shell screenrecord /sdcard/video.mp4 
Run Code Online (Sandbox Code Playgroud)

您甚至可以在Android Studio内部执行此操作.

问题

我找不到任何有关如何使用API​​的教程或解释,这在代码中是有意义的.

我发现了什么

我找到的唯一的地方是文件(这里,在"屏幕截图和分享"下),告诉我这个:

Android 5.0允许您使用新的android.media.projection API为您的应用添加屏幕捕获和屏幕共享功能.例如,如果要在视频会议应用中启用屏幕共享,此功能很有用.

createVirtualDisplay()方法允许您的应用程序将主屏幕的内容(默认显示)捕获到Surface对象中,然后您的应用可以通过网络发送该对象.API仅允许捕获非安全屏幕内容,而不是系统音频.要开始屏幕捕获,您的应用必须首先通过使用通过该createScreenCaptureIntent()方法获得的Intent启动屏幕捕获对话框来请求用户的许可.

有关如何使用新API的示例,请参阅示例项目中的MediaProjectionDemo类.

事实是,我找不到任何"MediaProjectionDemo"样本.相反,我发现了"屏幕截图"样本,但我不明白它是如何工作的,因为当我运行它时,我所看到的只是一个闪烁的屏幕,我不认为它将视频保存到一份文件.样本看起来非常错.

问题

如何使用新API执行这些操作:

  1. 开始录音,可选择包括音频(麦克风/扬声器/两者).
  2. 停止录音
  3. 截取屏幕截图而不是视频.

另外,我如何自定义它(分辨率,请求的fps,颜色,时间......)?

boz*_*mob 64

Ken White正确建议并且您可能已经涵盖的第一步是正式提供的示例代码.

我之前使用过他们的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);
    }
   }
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

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 
   }
  }
 }
Run Code Online (Sandbox Code Playgroud)

2.5.暂停和恢复视频录制

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

 private void resumeScreenRecord() {
  synchronized(sSync) {
   if (sMuxer != null) {
    sMuxer.resumeRecording();
   }
  }
 }
Run Code Online (Sandbox Code Playgroud)

希望代码有所帮助.这是我提到的代码的原始链接,并且也从中派生出此实现(视频录制).


3.截取屏幕而不是视频

我认为默认情况下它很容易以位图格式捕获图像.您仍然可以继续使用MediaProjectionDemo示例捕获屏幕截图.

[编辑]:代码加密截图

一个.根据设备宽度/高度创建虚拟显示

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);
Run Code Online (Sandbox Code Playgroud)

湾 然后根据意图或行动启动屏幕捕获 -

startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
Run Code Online (Sandbox Code Playgroud)

停止媒体投影 -

sMediaProjection.stop();
Run Code Online (Sandbox Code Playgroud)

C.然后转换为图像 -

//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();
Run Code Online (Sandbox Code Playgroud)

有几种可用的Media Projection API实现(完整代码).一些其他链接可以帮助您进行开发 -

  1. 使用MediaProjectionManager进行视频录制 - 网站

  2. android-ScreenCapture -根据android开发者的观察结果 github :)

  3. screenrecorder - github

  4. 使用MediaProjection API捕获并记录Android屏幕 - 网站


希望它有所帮助:)快乐的编码和屏幕录制!

PS:你能告诉我你正在谈论的微软应用吗?我没用过它.想尝试一下:)

  • 为什么他们这些API如此复杂? (7认同)
  • 完成!添加了最相关的代码和步骤,从Media Projection API中获取图像.希望能帮助到你 :) (5认同)