【问题标题】:How to record screen and take screenshots, using Android API?如何使用 Android API 录屏和截屏?
【发布时间】:2015-09-10 23:55:37
【问题描述】:

背景

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

自从新的 API 推出以来,很多应用都使用了这个功能,允许记录屏幕,微软甚至制作了自己的 Google-Now-On-tap 竞争对手应用。

使用 ADB,您可以使用:

adb shell screenrecord /sdcard/video.mp4 

您甚至可以在 Android Studio 中完成。

问题

我找不到任何关于如何使用 API 的教程或解释,这意味着在代码中。

我发现了什么

我找到的唯一地方是文档(here,在“屏幕捕获和共享”下),告诉我:

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

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

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

问题是,我找不到任何“MediaProjectionDemo”示例。相反,我找到了“屏幕捕获”示例,但我不明白它是如何工作的,因为当我运行它时,我所看到的只是一个闪烁的屏幕,我认为它不会将视频保存到一份文件。该示例似乎有很多错误。

问题

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

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

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

【问题讨论】:

  • 我在我的 D:\Android\android-sdk\samples\android-23\legacy\ApiDemos\src\com\example\android\apis\media\projection 文件夹中找到了一个参考(其中 D:\Android 是我的 SDK 文件的位置)。这有帮助吗?
  • @KenWhite 如何将 API 演示导入 Android-Studio?它们不应该只用于 Eclipse 吗?
  • 不,演示适用于任何开发环境。它们最初是为 Eclipse 设置的。至于如何导入它们,我不知道,但这不是你在这里问的。你说我找不到演示,我告诉你在哪里可以找到它。你有没有在任何地方搜索过How to use Eclipse code in Android Studio?之前有人问过吗?
  • 有点难(写在这里:code.google.com/p/android/issues/detail?id=186208),但现在我看,它也不包含任何与文件相关的内容,更不用说截图而不是视频录制... :(
  • 2019 年有一篇关于记录屏幕的各种方法的有用的相对较新的文章,这是链接medium.com/bolt-labs/… 我没有添加这个作为答案,因为我没有立即需要深入研究细节。尽管如此,我希望它至少对你们中的一些人有所帮助。

标签: android screenshot android-5.0-lollipop android-4.4-kitkat screen-recording


【解决方案1】:

Ken White 正确建议并且您可能已经介绍过的第一步是官方提供的Example Code

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

希望代码有所帮助。这是我提到的代码的original link,也是这个实现(视频录制)的来源。


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);

b.然后根据意图或动作启动屏幕捕获-

startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);

停止媒体投影-

sMediaProjection.stop();

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();

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

  1. Video Recording with MediaProjectionManager - 网站

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

  3. screenrecorder-github

  4. Capture and Record Android Screen using MediaProjection APIs - 网站


希望对您有所帮助 :) 编码和屏幕录制愉快!

PS:你能告诉我你说的微软应用吗?我没用过。想试试:)

【讨论】:

  • 我已经指出了如何截屏-github.com/mtsahakis/MediaProjectionDemo。这个演示有它。
  • 完成!添加了从媒体投影 API 中获取图像所需的最相关代码和步骤。希望它有所帮助:)
  • @Ewoks Screenshot 可在全球范围内使用,拍摄用户所见内容的照片,包括其他应用程序的照片。您编写的内容仅适用于当前应用。
  • @bozzmob 看来这段代码会导致左右透明边距。我在这里创建了一个关于它的新帖子:stackoverflow.com/q/43705756/878126
  • 他们为什么要让这些 API 如此复杂?
猜你喜欢
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 2012-02-11
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
相关资源
最近更新 更多