Android使⽤MediaProjectionManager完成录屏功能
Android 使⽤MediaProjectionManager 完成录屏功能
关于Android 视频录制功能,下⽂只介绍录制本机屏幕(不是使⽤摄像头来进⾏拍摄)
在Android5.0版本之后,系统给我们提供了**MediaProjectionManager** 和**MediaProjection** 来实现录制视频功能,⽬前市⾯的真机基本上都到Android6.0的阶段,所以该功能⼤家可以放⼼使⽤,下⾯就是具体步骤:
1.配置权限以及请求权限(Android6.0)
录屏⼀般需要两个权限,读写⽂件权限以及录⾳权限(视情况⽽定)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
2.进⾏请求系统录屏的回调
如果需要录制的内容就在本页⾯Activity(Fragment)中可以直接请求录屏,如果需要录制的内容是整个App进程中,就需要做些特别的处理,先有⼀个空⽩的Activity进⾏录屏请求,得到回调之后使⽤WindowManger添加⼀个View(⽅便进⾏交互),我介绍的就是后⾯⼀种:
1.空⽩页⾯进⾏录屏请求:
/**
* 实现录屏功能
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class ScreenRecordingActivity extends Activity {
public static final String TAG = "ScreenRecordingActivity";
private static final int STORAGE_REQUEST_CODE = 101;
private static final int RECORD_REQUEST_CODE = 201;
private MediaProjectionManager projectionManager;
private MediaProjection mediaProjection;
@Override
protected void onCreate(Bundle savedInstanceState) {
projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
requestPermission();
}
/**
* 请求录屏权限
*/
private void requestPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {  //
LogUtil.e(TAG,"该设配为Android5.0以下接⼝");
finish();
finish();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  //
boolean isSdCard = AppUtil.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, StringId(this, "missin            boolean isRecord = AppUtil.checkPermission(this, Manifest.permission.RECORD_AUDIO, "");
if (isSdCard && isRecord) {  //  有权限启动录屏
screenRecording();
} else {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, STORAGE_REQUEST_            }
} else {  //  5.0 和 5.1  进⾏录屏
screenRecording();
}
}
private void screenRecording() {
Intent captureIntent = ateScreenCaptureIntent();
startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
LogUtil.e(TAG,"可以进⾏录屏");
mediaProjection = MediaProjection(resultCode, data);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int orientation = getResources().getConfiguration().orientation;
Instance().showRecord().setRecorderConfig(mediaProjection,metrics,orientation).startRecorder();
finish();
}else { //
LogUtil.e(TAG,"⽤户取消了录屏");
finish();
}
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {//
switch (requestCode) {
case STORAGE_REQUEST_CODE:
LogUtil.e(TAG, "permissions:" + permissions);
LogUtil.e(TAG, "results:" + grantResults);
/
/ 只要不授权就返回
if (grantResults[0] == PackageManager.PERMISSION_GRANTED&&grantResults[1] == PackageManager.PERMISSION_GRANTED) {
screenRecording();
} else {
finish();
}
break;
default:
}
}
}
2.具体实现开始,暂停,重新开始,完成录制,导出⽂件等功能,录屏视图
/**
*  ⽤于结束录制以及显⽰录制时间的视图
*  Android5.0 以下的⼿机不允许使⽤录屏功能
*/
@Suppress("UNREACHABLE_CODE")
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class RecorderView private constructor() {
// 窗⼝管理器
private lateinit var mWM: WindowManager
// 管理器的参数
private lateinit var mWMParams: WindowManager.LayoutParams
// 上下⽂
private lateinit var mActivity: Activity
// 主视图
private lateinit var mMainView: LinearLayout
// 结束录制的按钮
private lateinit var mRecordFinishView: ImageView
// 显⽰录制的时间
private lateinit var mRecordTime: TimerTextView
/
/ 媒体
private lateinit var mediaProjection: MediaProjection
// 录屏类
private lateinit var mediaRecorder: MediaRecorder
// 虚拟屏幕,录屏或者截屏时创建的
private lateinit var virtualDisplay: VirtualDisplay
// 是否在录制
var isRecorder: Boolean = false
// 是否暂停
private var isPause: Boolean = false
private var width: Int = 720
private var height: Int = 1080
private var dpi: Int = 0
private var orientation: Int = 0 // 横竖屏标识
//  当前录制视频视频的路径
private lateinit var currentVideoFilePath: String
//  录制视频的集合
private lateinit var mediaPathList: ArrayList<String>
//  最后录屏完成之后的视频⽂件路径
private lateinit var saveMediaPath: String
companion object {
val TAG = "RecorderView"
val WINDOW_ORIGINAL_SIZE = 100f    // window ⼤⼩
@SuppressLint("StaticFieldLeak")
val instance = RecorderView()
}
/**
*  显⽰录屏按钮
*/
fun showRecord(): RecorderView {
mActivity = Instance().gameActivity  // 使⽤游戏的activity进⾏显⽰        initView()
initParams()
try {
mWM.addView(mMainView, mWMParams)
} catch (e: Exception) {
LogUtil.e(TAG, "添加视图异常:" + e.toString())
}
return this
}
/**
*  初始化录屏参数
*/
private fun initRecorder() {
mediaRecorder = MediaRecorder()
安卓intent用法if (dpi >= DisplayMetrics.DENSITY_XHIGH) {  // 视频最⼤的尺⼨ 720 * 1280 ,其他视频尺⼨使⽤屏幕⼤⼩
width = if (orientation != Configuration.ORIENTATION_LANDSCAPE) 720 else 1280
height = if (orientation != Configuration.ORIENTATION_LANDSCAPE) 1280 else 720
}
mediaRecorder.setOrientationHint(if (orientation != Configuration.ORIENTATION_LANDSCAPE) 0 else 90)
LogUtil.e("record", "当前录屏样式:" + if (orientation != Configuration.ORIENTATION_LANDSCAPE) "竖屏" else "横屏")
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT)  //  ⾳频源
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)  //  视频来源
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) //  视频输出格式
/
/
currentVideoFilePath = getRecorderDir()
mediaRecorder.setOutputFile(currentVideoFilePath)  // 录制输出⽂件名
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
mediaRecorder.setMaxDuration(1 * 60 * 1000)              // 设置最⼤时长5分钟
mediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024)  //  设置视频⽂件的⽐特率,经过测试该属性对于视频⼤⼩影响最⼤        mediaRecorder.setVideoSize(width, height)
mediaRecorder.setVideoFrameRate(30)
mediaRecorder.setOnErrorListener(OnRecordErrorListener()) // 录制发⽣错误的监听
mediaRecorder.setOnInfoListener(OnRecordInfoListener()) //
try {
mediaRecorder.prepare()
mediaPathList.add(currentVideoFilePath) // 调⽤⼀次该⽅法就在此处将加⼊集合
} catch (e: IOException) {
e.printStackTrace()
}
}
/**
* 初始化视图
*/
private fun initView() {
mMainView = AFResourceUtil.inflateViewByXML(mActivity, "window_record_ball") as LinearLayout
mRecordFinishView = mMainView.Id(mActivity, "iv_record")) as ImageView
mRecordTime = mMainView.Id(mActivity, "tv_time")) as TimerTextView
mRecordFinishView.setOnClickListener(OnRecordListener())
mediaPathList = arrayListOf()
}
/**
* 初始化布局参数
*/
private fun initParams() {
mWM = mActivity.windowManager
mWMParams = WindowManager.LayoutParams()
//noinspection ResourceType
// 设置悬浮求的背景为透明的
mWMParams.format = PixelFormat.RGBA_8888// 表⽰透明,下⾯可以看见
mWMParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS        // 设置固定在视图的中上部
// 宽⾼都设置为50 , 改变
mWMParams.width = SizeUtil.dip2px(mActivity, WINDOW_ORIGINAL_SIZE)
mWMParams.height = mWMParams.width
}
/**
*  设置录屏参数
*/
fun setRecorderConfig(mp: MediaProjection, displayMetrics: DisplayMetrics, orientation: Int): RecorderView {
width = displayMetrics.widthPixels
height = displayMetrics.heightPixels
dpi = displayMetrics.densityDpi
mediaProjection = mp
return this
}
/**
*  开始录屏
*/
fun startRecorder() {
if (orientation == 0) {
throw  RuntimeException("请先设置录屏参数")
}
if (!isRecorder) {  // 没有录屏时
LogUtil.e(TAG, "开始录屏")
startMedia()
isRecorder = true
mRecordTime.startTimer()
}
}
/**
* 暂停录制
* <p>
*  切换到后台就会触发暂停录制
*  将
* </p>
*/
fun pauseRecorder() {
if (isRecorder && !isPause) {
LogUtil.e(TAG, "执⾏暂停录制操作")
mRecordTime.pauseTimer()
isPause = true
stopMedia()
}
}
/**
*  重启录屏
*/
fun resumeRecorder() {
if (isRecorder && isPause) {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。