Android 实现屏幕录制和截屏

这篇具有很好参考价值的文章主要介绍了Android 实现屏幕录制和截屏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在移动开发中,实现屏幕录制和截屏是常见的需求。对于 Android 应用而言,实现屏幕录制和截屏可以帮助开发者更好地测试和调试自己的应用,同时还能够提供一些特定场景下的用户体验。

屏幕录制

Android 应用程序可以通过使用 MediaProjection API 来实现屏幕录制功能。使用此 API 可以获取指定屏幕的图像帧,并进行相关处理或保存为视频文件。

下面是一些简要的实现步骤:

  1. 获取 MediaProjection 对象:调用 MediaProjectionManager.createScreenCaptureIntent() 方法,启动屏幕捕获 Intent,并在 onActivityResult() 方法中获取 MediaProjection 对象。

  2. 创建虚拟显示器:使用 DisplayManager.createVirtualDisplay() 方法创建虚拟显示器,并将其与 MediaProjection 对象进行绑定。虚拟显示器将模拟真实屏幕并捕获图像帧。

  3. 获取屏幕截图:使用 MediaProjection.createVirtualDisplay() 的返回值创建 Surface 实例,并将其传递到 ImageReader.newInstance() 方法中,用于捕获指定屏幕的图像帧。

  4. 处理和编码每一帧图像:使用 ImageReader.acquireNextImage() 方法获取每一帧图像,并将其转换为 Bitmap 或 byte[] 形式。之后,可对图像进行自定义处理、压缩和编码操作,例如使用 MediaCodec 进行 H.264 编码等。

  5. 保存为视频文件:将每一帧图像数据按照音视频格式进行封装,写入 MP4 文件中。

需要注意的是,在 Android 5.0 以上版本中,启动屏幕捕获 Intent 需要授权,而且用户会受到屏幕被录制的通知。因此,要想隐藏通知,需要使用 SystemUI 系统应用程序或自己编写(需要 root 权限)。

在 Android 应用程序中实现屏幕录制,可以使用 MediaProjection API。具体实现步骤如下:

  1. 获取 MediaProjection 对象

在 Activity 中启动屏幕捕获 Intent,并在 onActivityResult() 方法中获取 MediaProjection 对象。

private static final int REQUEST_CODE = 1;
private MediaProjectionManager mMediaProjectionManager;
private MediaProjection mMediaProjection;

private void startScreenCapture() {
    mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
        mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
        startRecord();
    }
}
  1. 创建虚拟显示器

调用 MediaProjection.createVirtualDisplay() 方法创建一个虚拟显示器,该方法接受的参数包括显示器名称、显示器宽度、显示器高度、显示器 dpi、显示标识符等,并返回一个 VirtualDisplay 对象。

private static final int DISPLAY_FLAGS =
        DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
        DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
private static final int RECORD_WIDTH = 1280;
private static final int RECORD_HEIGHT = 720;
private static final int RECORD_DPI = 320;
private VirtualDisplay mVirtualDisplay;

private void startRecord() {
    // 创建 ImageReader 对象,用于从虚拟显示器中获取图像帧
    ImageReader imageReader = ImageReader.newInstance(RECORD_WIDTH, RECORD_HEIGHT, PixelFormat.RGBA_8888, 2);

    // 创建虚拟显示器,指定虚拟显示器的名称、宽度、高度、dpi 等参数
    mVirtualDisplay = mMediaProjection.createVirtualDisplay(
            "ScreenCapture",
            RECORD_WIDTH, RECORD_HEIGHT, RECORD_DPI,
            DISPLAY_FLAGS,
            imageReader.getSurface(), null, mHandler);
}
  1. 从 ImageReader 中获取图像帧并编码

调用 ImageReader.acquireLatestImage() 方法从 ImageReader 对象中获取最新一帧的图像数据,并将其转换为 Bitmap 对象。然后使用 MediaCodec API 将 Bitmap 编码为 H.264 格式的视频流。

private static final String MIME_TYPE = "video/avc";
private static final int FRAME_RATE = 30;
private static final int I_FRAME_INTERVAL = 1;
private static final int BIT_RATE = RECORD_WIDTH * RECORD_HEIGHT * 4 * 5; // 视频编码码率(比特率),计算方式参考 H.264 的标准
private static final int TIMEOUT_US = 10000;

private MediaCodec mEncoder;
private Surface mSurface;

private void startEncode() {
    try {
        // 创建 MediaCodec 对象,指定编码器类型、编码格式、采样率、比特率等参数
        mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
        MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, RECORD_WIDTH, RECORD_HEIGHT);
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); // 比特率
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE); // 帧率
        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL); // I帧间隔

        // 配置 MediaCodec 对象并启动
        mEncoder.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mSurface = mEncoder.createInputSurface();
        mEncoder.start();

        // 获取 ImageReader 中的图像数据并编码
        while (true) {
            Image image = mImageReader.acquireLatestImage();
            if (image == null) {
                continue;
            }

            // 将 Image 转化为 Bitmap 对象
            Image.Plane[] planes = image.getPlanes();
            int width = image.getWidth();
            int height = image.getHeight();
            ByteBuffer buffer = planes[0].getBuffer();
            int pixelStride = planes[0].getPixelStride();
            int rowStride = planes[0].getRowStride();
            int padding = rowStride - pixelStride * width;
            Bitmap bitmap = Bitmap.createBitmap(width + padding / pixelStride, height, Bitmap.Config.ARGB_8888);
            bitmap.copyPixelsFromBuffer(buffer);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);

            // 编码 Bitmap 数据
            long pts = System.nanoTime() / 1000;
            int inputIndex = mEncoder.dequeueInputBuffer(TIMEOUT_US);
            if (inputIndex >= 0) {
                Surface surface = mEncoder.createInputSurface();
                Canvas canvas = surface.lockCanvas(null);
                canvas.drawBitmap(bitmap, new Matrix(), null);
                surface.unlockCanvasAndPost(canvas);
                mEncoder.queueInputBuffer(inputIndex, 0, 0, pts, 0);
            }

            image.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

需要注意的是,在使用 MediaProjection API 进行屏幕录制时,需要获取用户的授权。同时在录制过程中,还需要处理好多个线程之间的同步关系,避免出现数据异常等情况。

截屏

在 Android 应用程序中实现屏幕截屏,通常可以使用以下两种方式:

  1. 使用 MediaProjection API:MediaProjection API 是 Android Framework 提供的一种机制,允许应用获取指定屏幕的图像帧,并进行相关处理或保存为视频文件。在屏幕截屏方面,开发者可以使用 MediaProjection.createVirtualDisplay() 方法创建虚拟显示器,并使用 ImageReader.acquireLatestImage() 方法获取最新的一帧图像,进而将其保存为图片文件。

具体实现过程如下:

// 在 Activity 中启动屏幕捕获 Intent,并在 onActivityResult() 方法中获取 MediaProjection 对象
private void startScreenCapture() {
    mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_MEDIA_PROJECTION && resultCode == RESULT_OK) {
        mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);

        // 创建虚拟显示器
        mVirtualDisplay = mMediaProjection.createVirtualDisplay(
                "ScreenCapture",
                mScreenWidth, mScreenHeight, mScreenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mImageReader.getSurface(), null, mHandler);
    }
}

// 在需要截屏的时候调用
private void takeScreenShot() {
    Image image = mImageReader.acquireLatestImage();
    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    byte[] bytes = new byte[buffer.capacity()];
    buffer.get(bytes);
    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

    // 将 Bitmap 保存为本地文件
    File file = new File(Environment.getExternalStorageDirectory(), "screenshot.png");
    FileOutputStream outputStream = null;
    try {
        outputStream = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
        Log.d(TAG, "ScreenShot Saved");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        image.close();
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

需要注意的是,在 Android 5.0 及以上版本中,启动屏幕捕获 Intent 需要授权,而且用户会受到屏幕被录制的通知。如果要想避免这种情况,需要使用 SystemUI 系统应用程序或自己编写(需要 root 权限)。

  1. 使用 View 的 draw() 方法:在 View 的绘制过程中,可以通过调用 View 的 draw(Canvas canvas) 方法来获取其绘制区域的内容,并将其保存为图片文件。具体实现方式如下:
// 创建一个 View
View view = getWindow().getDecorView();

// 创建 Bitmap 并将 View 绘制到画布上
Bitmap bm = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
view.draw(canvas);

// 将 Bitmap 保存到本地文件中
File saveDir = Environment.getExternalStorageDirectory();
File file = new File(saveDir, "screenshot.png");
OutputStream outputStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();

需要注意的是,该方法只适用于当前应用程序内部界面的截图。如果想要截取其他应用程序、系统界面或整个屏幕的截图,则需要使用 MediaProjection API 实现。

长截屏

实现长截屏的方法一般是通过将多个屏幕截图拼接在一起。下面是一些实现长截屏的步骤以及相关代码示例:

  1. 获取屏幕宽度和高度
DisplayMetrics metrics = getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
  1. 创建一个空的 Bitmap 对象用于保存所截取的屏幕内容
Bitmap longScreenshot = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
  1. 获取当前屏幕的 View 对象并将其绘制到 Bitmap 中
View screenshotView = getWindow().getDecorView().getRootView();
Canvas canvas = new Canvas(longScreenshot);
screenshotView.draw(canvas);
  1. 循环获取当前 View 的滚动位置并将其截取下来,然后将其拼接到 longScreenshot 中
while (scrollY < totalHeight) {
    scrollView.scrollTo(0, scrollY);
    Bitmap bitmap = Bitmap.createBitmap(scrollView.getWidth(), scrollView.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    scrollView.draw(canvas);
    canvas.drawBitmap(bitmap, 0, scrollY, null);
    scrollY += scrollView.getHeight();
}

longScreenshot.compress(Bitmap.CompressFormat.PNG, 100, outputStream);

完整代码示例请参考:

private void takeLongScreenshot() {
    // 获取屏幕宽度和高度
    DisplayMetrics metrics = getResources().getDisplayMetrics();
    int width = metrics.widthPixels;
    int height = metrics.heightPixels;
    
    // 创建一个空的 Bitmap 对象用于保存所截取的屏幕内容
    Bitmap longScreenshot = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    
    // 获取当前屏幕的 View 对象并将其绘制到 Bitmap 中
    View screenshotView = getWindow().getDecorView().getRootView();
    Canvas canvas = new Canvas(longScreenshot);
    screenshotView.draw(canvas);
    
    // 循环获取当前 View 的滚动位置并将其截取下来,然后将其拼接到 longScreenshot 中
    int scrollY = screenshotView.getHeight();
    ScrollView scrollView = findViewById(R.id.scroll_view);
    int totalHeight = scrollView.getChildAt(0).getHeight();
    while (scrollY < totalHeight) {
        scrollView.scrollTo(0, scrollY);
        Bitmap bitmap = Bitmap.createBitmap(scrollView.getWidth(), scrollView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas1 = new Canvas(bitmap);
        scrollView.draw(canvas1);
        canvas.drawBitmap(bitmap, 0, scrollY, null);
        scrollY += scrollView.getHeight();
    }
    
    // 将拼接后的长截屏保存到文件中
    try {
        FileOutputStream outputStream = new FileOutputStream(getExternalFilesDir(null) + "/long_screenshot.png");
        longScreenshot.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
        outputStream.flush();
        outputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

需要注意的是,由于手机屏幕宽度和高度有限,因此一些页面可能无法完全截取。同时,由于 Android 系统版本和不同厂商的定制系统可能存在差异,因此上述代码并不能保证在所有情况下都能正常工作。文章来源地址https://www.toymoban.com/news/detail-614637.html

到了这里,关于Android 实现屏幕录制和截屏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android App保护用户隐私————禁止应用截屏或录屏

           相信大家在使用某些平台应用的时候,都会有 限制的规定 。        通常情况下,录屏、截图软件都可以在手机的运行过程中进行录屏、截图,普通的平台也不会阻止录屏、截图软件运行。        但是在某些比较 敏感 的平台上面,有可能出于 保密 的原因

    2024年02月02日
    浏览(75)
  • Android屏幕录制

    这里使用Java语言编写实现,完整代码如下: 文件 AndroidMainfest.xml 的主要配置 文件activity_screen_recording.xml的内容 文件ScreenRecordingActivity.java的完整代码 文件 ScreenRecordingService.java 的完整代码 特别鸣谢下面链接: (0)  https://blog.csdn.net/qq_46546793/article/details/123279152 (0)  https://blog

    2024年02月09日
    浏览(31)
  • 苹果录屏功能在哪?苹果如何进行屏幕录制?

    【用苹果手机和电脑很久了,但是我还是不知道它们的录屏功能在哪,如何使用?有没有小伙伴了解苹果的录屏功能?可以教教我吗?】 苹果手机和电脑自带了非常方便的录屏功能,可以帮助您轻松地录制屏幕上的内容,包括 教程演示、游戏操作、软件演示 等等。但是很多

    2024年02月05日
    浏览(58)
  • 电脑怎么录屏?推荐2款录制电脑屏幕的软件!

    案例:我经常需要把电脑上的内容分享给别人,一般通过手机拍摄的方式。这就导致视频十分模糊,给人的观感不太好,有没有什么方法可以实现在电脑上直接录屏? 【我想录制我的电脑屏幕上的内容分享给别人,但是我不知道如何操作。听说使用录屏工具可以快速录制电脑

    2024年02月09日
    浏览(34)
  • PPT屏幕录制怎么关闭?一招教你退出PPT录屏

    由于PPT录制界面会隐藏控制面板,有很多小伙伴在录制PPT文档时会遇到这样的问题:录制完成之后不知道如何关闭PPT屏幕录制。屏幕前的你知道PPT屏幕录制怎么关闭吗?如果您也不知道的话,可以阅读下方文章。 今天小编会给大家带来关闭PPT录制的详细方法,快来看看如何一

    2023年04月22日
    浏览(134)
  • 电脑如何录屏?分享4个屏幕录制的好方法,建议收藏

    电脑录制画面是一件非常简单的事情,在电脑上打开相应软件就可以轻松的录制电脑屏幕上正在进行的操作了。但是很多朋友并不清楚如何录制电脑上各个窗口的内容,比如游戏、文档等等。 那么电脑如何录屏?下面分享分享4个屏幕录制的好方法。 win10自带录屏在哪?Wind

    2024年02月12日
    浏览(48)
  • 录屏软件电脑版免费哪个好?4款免费屏幕录制软件下载

    在电脑上经常能使用的录屏功能:录制软件的操作过程、精彩的游戏瞬间、经典的影视故事、网络教学等。许多人都在问,录屏软件电脑版哪个好?Windows平台上有很多录屏软件,如果对录屏需求不高的朋友,可以通过内置的视频软件进行录制;想要录制高清无损的视频,可以

    2024年02月06日
    浏览(67)
  • Android 截屏实现的几种方式

    image.png image.png 1、View 截屏 View 截图是将当前 View 界面截取下来,而对于屏幕上其他信息比如:状态栏或其他应用的界面将无法截取。 1.1 截取除了导航栏之外的屏幕 1.2 截取某个控件或者区域 2、WebView 截屏 WebView 截屏有四种方式 2.1 使用 capturePicture() 方法(已废弃) private

    2024年02月06日
    浏览(40)
  • Android View转换为Bitmap,实现截屏效果

            安卓设备一般都自带截图功能,但是用户体验有不好之处。就是会连带着状态栏📶、🔋、时间日期、其他不必要页面中信息,等等与用户想截屏的内容不符的信息也会被保存下来。通常,截图后用户会再次裁剪一次才能想把真正需求分享出去。         因此,咱们

    2023年04月08日
    浏览(49)
  • 微信小程序在某个页面防止用户截屏、录屏实现

    好吧!好吧!项目~又来搞事情了,想在预览图片的时候监听图片长按菜单的“保存图片”操作,因为在这有个查询用户是否有保存图片的权限,没有的话就不能把图片保存到手机,但是查了半天,发现根本无法监听到长按菜单的对应操作(分享朋友、保存图片等等),干脆把

    2024年02月05日
    浏览(342)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包