MediaRecorder類介紹:
在察哈爾右翼中旗等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供網(wǎng)站制作、成都網(wǎng)站設計 網(wǎng)站設計制作按需搭建網(wǎng)站,公司網(wǎng)站建設,企業(yè)網(wǎng)站建設,品牌網(wǎng)站制作,全網(wǎng)整合營銷推廣,成都外貿(mào)網(wǎng)站制作,察哈爾右翼中旗網(wǎng)站建設費用合理。
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)判斷是否錄屏授權(quán)的Activity
其中intent對象就需要MediaProjectionManager.createScreenCaptureIntent();獲取
2、在onActivityResult回調(diào)方法中做具體錄屏工作
比如:創(chuàng)建MediaRecorder,設置MP4文件路徑
創(chuàng)建VirtualDisplay,設置屏幕相關(guān)參數(shù)
如果不在onActivityResult回調(diào)中執(zhí)行會有問題。
3、開始錄屏
MediaRecorder.start()
4、停止錄屏
MediaRecorder.reset();
MediaRecorder.release();
錄屏過程用到錄音權(quán)限和數(shù)據(jù)讀寫權(quán)限。
三、MediaCodec和MediaMuxer
MediaCodec提供對音視頻壓縮編碼和解碼功能,MediaMuxer可以將音視頻混合生成多媒體文件,生成MP4文件。
這個錄屏的方式和MediaRecorder是類似的,只是流程第二部有點不同,這里不做介紹。
詳情可以參考:https://www.jb51.net/article/183324.htm
四、MediaRecorder項目示例的主要代碼
這里只做了錄制和停止錄制,沒有做相關(guān)適配,比如橫豎屏切換后尺寸變化。
簡單效果:
生成的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; //錄音權(quán)限和數(shù)據(jù)讀寫權(quán)限 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() { //權(quán)限申請 //逐個判斷你要的權(quán)限是否已經(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); } // 申請權(quán)限后的回調(diào) // 1、錄音和讀寫 // 2、錄屏startActivityForResult后的回調(diào) @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //錄音和讀寫權(quán)限 if (requestCode == REQUEST_CODE_PERMISSIONS) { if (resultCode != Activity.RESULT_OK) { mPassPermissions = false; } } else // 錄屏權(quán)限 if (requestCode == REQUEST_CODE_SCREEN) { if (resultCode == Activity.RESULT_OK) { try { // mediaProjection 如果不在權(quán)限申請中回調(diào),獲取到的對象為空 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, "基礎權(quán)限沒通過!", 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) { //存在錄屏授權(quán)的Activity startActivityForResult(intent, REQUEST_CODE_SCREEN); } else { Toast.makeText(this, "沒有錄屏權(quán)限!", 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; } } }; //判斷每個權(quán)限是否通過 private void judgePermissions() { boolean permission = true; for (int i = 0; i < permissions.length; i++) { if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) { // 未授予的權(quán)限 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()方法后調(diào)用 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
這個項目只是簡單錄屏,如果要做得好,
最好是正在通知欄/懸浮框里面控制停止,
并且可以按退出鍵回到主界面,
要用到服務來控制錄屏屏幕的開始和停止。
共勉:時間總會過去,多做一下有意義的事情。
總結(jié)
到此這篇關(guān)于Android錄屏 MediaRecorder介紹的文章就介紹到這了,更多相關(guān)android錄屏 mediaRecorder內(nèi)容請搜索創(chuàng)新互聯(lián)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持創(chuàng)新互聯(lián)!
當前文章:淺析Android錄屏MediaRecorder
網(wǎng)站URL:http://m.newbst.com/article24/pooece.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供云服務器、做網(wǎng)站、用戶體驗、商城網(wǎng)站、動態(tài)網(wǎng)站、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)