浅析Android录屏 MediaRecorder

您所在的位置:网站首页 华为nova5i有没有录屏功能视频功能呢 浅析Android录屏 MediaRecorder

浅析Android录屏 MediaRecorder

2023-04-17 18:10| 来源: 网络整理| 查看: 265

MediaRecorder类介绍:

MediaRecorder类是Android sdk提供的一个专门用于音视频录制,一般利用手机麦克风采集音频,摄像头采集图片信息。

Android录屏的三种方案

1、adb shell命令screenrecord 2、MediaRecorder, MediaProjection 3、MediaCodec和MediaMuxer, MediaProjection ,

一、screenrecord命令

screenrecord是一个shell命令,支持Android4.4(API level 19)以上, 录制的视频格式为mp4 ,存放到手机sd卡里,默认录制时间为180s

adb shell screenrecord –size 1280×720 –bit-rate 6000000 –time-limit 30 /sdcard/demo.mp4 –size 指定视频分辨率,根据手机情况决定 –bit-rate 指定视频比特率,默认为4M,该值越小,保存的视频文件越小; –time-limit 指定录制时长,若设定大于180,命令不会被执行;

并不是所以手机都执行screenrecord命令,部分手机不识别。 我在几款华为手机就没执行成功报错: /system/bin/sh: screenrecord: inaccessible or not found

二、 MediaRecorder

MediaProjection是Android5.0后才开放的屏幕采集接口,通过系统级服务MediaProjectionManager进行管理。

这里先整体说一下屏幕录制的流程,不然看起来费劲。

1、通过startActivityForResult(Intent intent)判断是否录屏授权的Activity

其中intent对象就需要MediaProjectionManager.createScreenCaptureIntent();获取

2、在onActivityResult回调方法中做具体录屏工作

比如:创建MediaRecorder,设置MP4文件路径 创建VirtualDisplay,设置屏幕相关参数 如果不在onActivityResult回调中执行会有问题。

3、开始录屏

MediaRecorder.start()

4、停止录屏

MediaRecorder.reset(); MediaRecorder.release();

录屏过程用到录音权限和数据读写权限。

三、MediaCodec和MediaMuxer

MediaCodec提供对音视频压缩编码和解码功能,MediaMuxer可以将音视频混合生成多媒体文件,生成MP4文件。

这个录屏的方式和MediaRecorder是类似的,只是流程第二部有点不同,这里不做介绍。

详情可以参考:https://www.zalou.cn/article/183324.htm

四、MediaRecorder项目示例的主要代码

这里只做了录制和停止录制,没有做相关适配,比如横竖屏切换后尺寸变化。

简单效果:

生成的MP4文件会在sdcard目录下,并且以录屏时间为文件名。

1、MainActivity

package com.liwenzhi.screen; import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.media.projection.MediaProjection; import android.media.projection.MediaProjectionManager; import android.os.Handler; import android.os.Message; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.io.File; public class MainActivity extends AppCompatActivity implements View.OnClickListener { String TAG = "MainActivity"; MediaProjectionManager mProjectionManager; MediaRecordService mediaRecord; int displayWidth = 1280; int displayHeight = 1920; Button btn_start_record; Button btn_stop_record; TextView tv_time; int REQUEST_CODE_PERMISSIONS = 99; int REQUEST_CODE_SCREEN = 100; //录音权限和数据读写权限 String[] permissions = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; boolean mPassPermissions = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); initEvent(); } private void initView() { btn_start_record = findViewById(R.id.btn_start_record); btn_stop_record = findViewById(R.id.btn_stop_record); tv_time = findViewById(R.id.tv_time); } private void initData() { //权限申请 //逐个判断你要的权限是否已经通过 judgePermissions(); if (!mPassPermissions) { ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE_PERMISSIONS); } } private void initEvent() { btn_start_record.setOnClickListener(this); btn_stop_record.setOnClickListener(this); } // 申请权限后的回调 // 1、录音和读写 // 2、录屏startActivityForResult后的回调 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //录音和读写权限 if (requestCode == REQUEST_CODE_PERMISSIONS) { if (resultCode != Activity.RESULT_OK) { mPassPermissions = false; } } else // 录屏权限 if (requestCode == REQUEST_CODE_SCREEN) { if (resultCode == Activity.RESULT_OK) { try { // mediaProjection 如果不在权限申请中回调,获取到的对象为空 MediaProjection mediaProjection = mProjectionManager.getMediaProjection(resultCode, data); if (mediaProjection == null) { Log.e(TAG, "media projection is null"); return; } File file = new File("/sdcard/" + MyTimeUtils.getTimeString("yyyy-MM-dd_HH:mm:ss") + ".mp4"); //录屏生成文件 if (!file.exists()) { file.createNewFile(); } mediaRecord = new MediaRecordService(displayWidth, displayHeight, 6000000, 1, mediaProjection, file.getAbsolutePath()); mediaRecord.start(); second = 0; mHandler.sendEmptyMessageDelayed(10, 1000); } catch (Exception e) { e.printStackTrace(); } } else { Toast.makeText(MainActivity.this, "录屏失败", Toast.LENGTH_LONG).show(); } } } @Override public void onBackPressed() { //super.onBackPressed(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_start_record: startRecord(); break; case R.id.btn_stop_record: stopRecord(); break; } } // 开始录屏 private void startRecord() { judgePermissions(); if (!mPassPermissions) { Toast.makeText(this, "基础权限没通过!", Toast.LENGTH_LONG).show(); return; } mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); if (mProjectionManager != null) { Intent intent = mProjectionManager.createScreenCaptureIntent(); PackageManager packageManager = getPackageManager(); if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { //存在录屏授权的Activity startActivityForResult(intent, REQUEST_CODE_SCREEN); } else { Toast.makeText(this, "没有录屏权限!", Toast.LENGTH_LONG).show(); } } } // 停止录屏 private void stopRecord() { mediaRecord.release(); mHandler.removeMessages(10); } int second; // 计算时间 Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 10: second++; tv_time.setText(second + ""); mHandler.sendEmptyMessageDelayed(10, 1000); break; } } }; //判断每个权限是否通过 private void judgePermissions() { boolean permission = true; for (int i = 0; i < permissions.length; i++) { if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) { // 未授予的权限 permission = false; } } mPassPermissions = permission; } }

2、MediaRecordService

package com.liwenzhi.screen; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.media.MediaRecorder; import android.media.projection.MediaProjection; import android.util.Log; public class MediaRecordService extends Thread { private static final String TAG = "MediaRecordService"; private int mWidth; private int mHeight; private int mBitRate; private int mDpi; private String mDstPath; private MediaRecorder mMediaRecorder; private MediaProjection mMediaProjection; private static final int FRAME_RATE = 60; // 60 fps private VirtualDisplay mVirtualDisplay; public MediaRecordService(int width, int height, int bitrate, int dpi, MediaProjection mp, String dstPath) { mWidth = width; mHeight = height; mBitRate = bitrate; mDpi = dpi; mMediaProjection = mp; mDstPath = dstPath; } @Override public void run() { try { initMediaRecorder(); //在mediarecorder.prepare()方法后调用 mVirtualDisplay = mMediaProjection.createVirtualDisplay(TAG + "-display", mWidth, mHeight, mDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC, mMediaRecorder.getSurface(), null, null); Log.i(TAG, "created virtual display: " + mVirtualDisplay); mMediaRecorder.start(); Log.i(TAG, "mediarecorder start"); } catch (Exception e) { e.printStackTrace(); } } /** * 初始化MediaRecorder * * @return */ public void initMediaRecorder() { mMediaRecorder = new MediaRecorder(); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mMediaRecorder.setOutputFile(mDstPath); mMediaRecorder.setVideoSize(mWidth, mHeight); mMediaRecorder.setVideoFrameRate(FRAME_RATE); mMediaRecorder.setVideoEncodingBitRate(mBitRate); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); try { mMediaRecorder.prepare(); } catch (Exception e) { e.printStackTrace(); } Log.i(TAG, "media recorder" + mBitRate + "kps"); } public void release() { if (mVirtualDisplay != null) { mVirtualDisplay.release(); mVirtualDisplay = null; } if (mMediaRecorder != null) { mMediaRecorder.setOnErrorListener(null); mMediaProjection.stop(); mMediaRecorder.reset(); mMediaRecorder.release(); } if (mMediaProjection != null) { mMediaProjection.stop(); mMediaProjection = null; } Log.i(TAG, "release"); } }

3、MyTimeUtils

package com.liwenzhi.screen; import java.text.SimpleDateFormat; import java.util.Date; /** * a Utils for time *


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3