欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺析Android錄屏 MediaRecorder

 更新時間:2020年03月23日 14:45:49   作者:崢嶸life  
MediaRecorder類是Android sdk提供的一個專門用于音視頻錄制,一般利用手機麥克風采集音頻,攝像頭采集圖片信息。這篇文章主要介紹了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 指定視頻分辨率,根據(jù)手機情況決定
 --bit-rate 指定視頻比特率,默認為4M,該值越小,保存的視頻文件越小;
 --time-limit 指定錄制時長,若設定大于180,命令不會被執(zhí)行;

并不是所以手機都執(zhí)行screenrecord命令,部分手機不識別。
我在幾款華為手機就沒執(zhí)行成功報錯:
/system/bin/sh: screenrecord: inaccessible or not found

二、 MediaRecorder

MediaProjection是Android5.0后才開放的屏幕采集接口,通過系統(tǒng)級服務MediaProjectionManager進行管理。

這里先整體說一下屏幕錄制的流程,不然看起來費勁。

1、通過startActivityForResult(Intent intent)判斷是否錄屏授權的Activity

其中intent對象就需要MediaProjectionManager.createScreenCaptureIntent();獲取

2、在onActivityResult回調方法中做具體錄屏工作

比如:創(chuàng)建MediaRecorder,設置MP4文件路徑
創(chuàng)建VirtualDisplay,設置屏幕相關參數(shù)
如果不在onActivityResult回調中執(zhí)行會有問題。

3、開始錄屏

MediaRecorder.start()

4、停止錄屏

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

錄屏過程用到錄音權限和數(shù)據(jù)讀寫權限。

三、MediaCodec和MediaMuxer

MediaCodec提供對音視頻壓縮編碼和解碼功能,MediaMuxer可以將音視頻混合生成多媒體文件,生成MP4文件。

這個錄屏的方式和MediaRecorder是類似的,只是流程第二部有點不同,這里不做介紹。

詳情可以參考:http://www.dbjr.com.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;
 //錄音權限和數(shù)據(jù)讀寫權限
 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() {
 //權限申請
 //逐個判斷你要的權限是否已經(jīng)通過
 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內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Android中ContentProvider和ContentResolver詳解

    Android中ContentProvider和ContentResolver詳解

    這篇文章主要介紹了Android中ContentProvider和ContentResolver詳解的相關資料,需要的朋友可以參考下
    2017-04-04
  • Android實現(xiàn)短信發(fā)送功能

    Android實現(xiàn)短信發(fā)送功能

    這篇文章主要介紹了Android實現(xiàn)短信發(fā)送功能,對Android實現(xiàn)短信發(fā)送的每一步都進行了詳細的介紹,感興趣的小伙伴們可以參考一下
    2015-12-12
  • Android實現(xiàn)記住用戶名和密碼功能

    Android實現(xiàn)記住用戶名和密碼功能

    登陸界面創(chuàng)建一個復選按鈕,通過按鈕選取來進行事件處理。若按鈕選中記住賬號和密碼的信息,本文教大家如何使用Android實現(xiàn)記住用戶名和密碼功能,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Kotlin 創(chuàng)建接口或者抽象類的匿名對象實例

    Kotlin 創(chuàng)建接口或者抽象類的匿名對象實例

    這篇文章主要介紹了Kotlin 創(chuàng)建接口或者抽象類的匿名對象實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android?IdleHandler使用方法詳解

    Android?IdleHandler使用方法詳解

    這篇文章主要為大家介紹了Android?IdleHandler使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • Android 屏幕實現(xiàn)上下翻轉

    Android 屏幕實現(xiàn)上下翻轉

    這篇文章主要介紹了Android 屏幕實現(xiàn)上下翻轉的相關資料,需要的朋友可以參考下
    2017-07-07
  • android與asp.net服務端共享session的方法詳解

    android與asp.net服務端共享session的方法詳解

    這篇文章主要給大家介紹了關于android與asp.net服務端如何共享session的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋們下面隨著小編來一起學習學習下吧。
    2017-09-09
  • Android自定義控件案例匯總1(菜單、popupwindow、viewpager)

    Android自定義控件案例匯總1(菜單、popupwindow、viewpager)

    這篇文章主要介紹了Android自定義控件案例匯總,優(yōu)酷菜單、popupwindow實現(xiàn)下拉列表、viewpager實現(xiàn)輪播圖,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Android使用SoundPool播放短音效

    Android使用SoundPool播放短音效

    這篇文章主要為大家詳細介紹了Android使用SoundPool播放短音效,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Android自定義ViewPager實例

    Android自定義ViewPager實例

    這篇文章主要介紹了Android自定義ViewPager的方法,結合完整實例形式分析了Android基于ViewGroup類自定義ViewPager的具體實現(xiàn)技巧,需要的朋友可以參考下
    2016-02-02

最新評論