浅析Android录屏 MediaRecorder

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 1280x720 --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.jb51.net/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
 * <p>
 * identify the following letter: :"yyyy-MM-dd DD HH:mm:ss SSS"
 * * method1: long getTimeLong()
 * * method2: int getTimeInt(String filter)
 * * method3: String getTimeString()
 * * method4: String getTimeString(long time)
 * * method5: String getTimeString(long time, String filter)
 * * method6: String getTimeString( String filter)
 */
public class MyTimeUtils {
 public static long getTimeLong() {
 return System.currentTimeMillis();
 }
 public static int getTimeInt(String filter) {
 SimpleDateFormat format = new SimpleDateFormat(filter);
 String time = format.format(new Date());
 return Integer.parseInt(time);
 }
 public static final String getTimeString() {
 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 return format.format(new Date(getTimeLong()));
 }
 public static final String getTimeString(long time) {
 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 return format.format(new Date(time));
 }
 public static final String getTimeString(long time, String filter) {
 SimpleDateFormat format = new SimpleDateFormat(filter);
 return format.format(new Date(time));
 }
 public static final String getTimeString(String filter) {
 SimpleDateFormat format = new SimpleDateFormat(filter);
 return format.format(new Date(getTimeLong()));
 }
 public static Long getTimeLong(String filter, String date) {
 try {
  SimpleDateFormat format = new SimpleDateFormat(filter);
  Date dateTime = format.parse(date);
  return dateTime.getTime();
 } catch (Exception e) {
  e.printStackTrace();
 }
 return 0L;
 }
}

测试apk和项目源码下载:

http://xiazai.jb51.net/202003/yuanma/RecordMedia_jb51.rar

这个项目只是简单录屏,如果要做得好,
最好是正在通知栏/悬浮框里面控制停止,
并且可以按退出键回到主界面,
要用到服务来控制录屏屏幕的开始和停止。

共勉:时间总会过去,多做一下有意义的事情。

总结

到此这篇关于Android录屏 MediaRecorder介绍的文章就介绍到这了,更多相关android录屏 mediaRecorder内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • android视频截屏&手机录屏实现代码

    本文介绍了android视频截屏&手机录屏实现代码,分享给大家,希望对大家有帮助 问题 在android中有时候我们需要对屏幕进行截屏操作,单一的截屏操作好解决可以通过activity的顶层view DecorView获取一个bitmap,得到就是当前activity上面的全部视图. View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(

  • Android中手机录屏并转换GIF的两种方式

    之前在博文中为了更好的给大家演示APP的实现效果,本人了解学习了几种给手机录屏的方法,今天就给大家介绍两种我个人用的比较舒服的两种方法: (1)配置adb环境后,使用cmd命令将手机界面操作演示存为视频文件 (2)使用Google浏览器(Google Chrome)提供的扩展程序Vysor将手机界面演示在电脑上(几乎没有延时羡慕) 下面我们具体介绍两种方法的使用步骤: 一.使用cmd命令录屏 (1)SDK下载 网上有各种SDK下载的方法,个人认为安装AndroidStudio后连接自己的手机,根

  • 详解有关Android截图与录屏功能的学习

    简单的截屏和录屏功能. 因为MediaProjection是5.0以上才出现的,所以今天所讲述功能实现,只在5.0以上的系统有效. 截屏: 步骤如下: 1:获取MediaProjectionManager 2:通过MediaProjectionManager.createScreenCaptureIntent()获取Intent 3:通过startActivityForResult传入Intent然后在onActivityResult中通过MediaProjectionManager.getMe

  • Android5.0以上版本录屏实现代码(完整代码)

    我录屏的方式是分别录制音频和视频,最后合并成mp4格式,比较麻烦,因为网上完整的教程比较少,所以我打算写一个完整版的,照着我的代码写完之后,至少是能够实现功能的,而不是简单的介绍下用法. 1既然是录制视频,我们应该有一个按钮控制开始和结束. 2在录制之前,需要先判断一下Android系统的版本是否大于5.0,并且动态申请一下权限(读写,录音,照相机),这一步可以在点开始按钮的时候执行 if (ContextCompat.checkSelfPermission(context, Manifest.

  • android设置adb自带screenrecord录屏命令

    android 设置system/bin目录类似linux,该目录下有许多实用命令,类似 adb,sh,top,app_process,chmod,chown,dmesg,reboot,screenrecord等等. 录屏作用:qa测试过程中有的bug需要还原现场,此时用手机拍摄有诸多不便,此时可以利用录屏命令自动完成录屏,然后上传bug视频. 其中screenrecord命令录制视频到内部存储: 录制命令: adb shell screenrecord --size 1920x480 /sto

  • 浅析Android录屏 MediaRecorder

    MediaRecorder类介绍: MediaRecorder类是Android sdk提供的一个专门用于音视频录制,一般利用手机麦克风采集音频,摄像头采集图片信息. Android录屏的三种方案 1.adb shell命令screenrecord 2.MediaRecorder, MediaProjection 3.MediaCodec和MediaMuxer, MediaProjection , 一.screenrecord命令 screenrecord是一个shell命令,支持Android

  • Android录屏的三种解决方案

    本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCodec和MediaMuxer screenrecord命令 screenrecord是一个shell命令,支持Android4.4(API level 19)以上,录制的视频格式为mp4 ,存放到手机sd卡里,默认录制时间为180s adb shell screenrecord --size 1280

  • Android录屏功能的实现

    最近做一个Android开发的项目用到了录屏的功能,开始查阅了一些资料和博客,基本上都是在讨论ROOT的.直到后来在github上看到一个比较新的代码,才恍然发现,Android 5.0时候开放了一个新的接口---android.media.projection,一下子让这个问题变得简单了.所以说查阅资料也该注意实时性,现在很多技术推陈出新速度很快,一些新的包,接口,方法会让问题更好更快的解决.不过自己还是决定总结了下之前的一些想法,也算是一个学习吧. 首先说下之前的几种方法.一般最开始的 An

  • android MediaRecorder实现录屏时带录音功能

    下面说说android的事把 最近是不是也会遇到需求中需要用到录屏录音的功能,最近也是遇到的 现在整理完记录一下 首先呢,录音录屏需要权限 先贴一个动态权限类 public class TalAllow { /** * RECORD_AUDIO 音频权限 * WRITE_EXTERNAL_STORAGE 写入权限 * CAMERA 相机权限 */ public static void requestPermissions(Context context,int allowCode) { Arra

  • android实现录屏小功能

    本文实例为大家分享了android实现录屏小功能的具体代码,供大家参考,具体内容如下 思路 android实现录屏功能有两种方案,一种是直接使用android自带的MediaProjectionManager实现录屏功能,第二种是是只录语音,用户的操作通过某种方式进行记录保存,最后通过某种协议进行播放. 两种方案各有各的优缺点,前者实现方式简单,但无法只录制特定区域的画面,并且生成的视频文件一般都比较大.后者实现较为繁琐,音频录制android7.0之前没有暂停方法,只能生成多个文件,然后对音频

  • android实现录屏功能

    本文实例为大家分享了android实现录屏功能的具体代码,供大家参考,具体内容如下 1.mian.activity package com.fpt.screenvideo; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.media.projection.MediaProjectionManager; import androi

  • Android开发实现录屏小功能

    最近开发中,要实现录屏功能,查阅相关资料,发现调用 MediaProjectionManager的api 实现录屏功能即可: import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.media.project

  • 浅析Android 手机卫士设备管理权限锁屏

    推荐阅读: 浅析Android手机卫士sim卡绑定 深入浅析Android手机卫士保存密码时进行md5加密 详解Android 手机卫士设置向导页面 浅析Android手机卫士关闭自动更新 浅析Android手机卫士自定义控件的属性 浅析Android手机卫士读取联系人 浅析Android手机卫士接收短信指令执行相应操作 浅析Android手机卫士手机定位的原理 浅析Android手机卫士之手机实现短信指令获取位置 设备管理员 Device Admin 获取DevicePolicyManager

  • android桌面悬浮窗显示录屏时间控制效果

    本文实例为大家分享了android桌面悬浮窗,实现录屏时间控制显示效果的具体代码,供大家参考,具体内容如下 悬浮窗效果如上图所示: 很简单的一个布局直接上代码 悬浮窗布局如下record_screen_time_float.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/an

随机推荐