简单屏幕录制截屏工具
生活随笔
收集整理的這篇文章主要介紹了
简单屏幕录制截屏工具
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
很久沒寫了,隨便寫寫~~
額,這是一個很簡單的截屏工具,用的是Android系統(tǒng)的MediaProjectionManager實現(xiàn)截屏錄制功能
使用到的主要類:
| MediaProjectionManager | MediaProjection管理 |
| MediaProjection | 授予捕獲屏幕或記錄系統(tǒng)音頻的功能 |
| VirtualDisplay | 個人理解類似虛擬屏幕?捕獲屏幕后將數(shù)據(jù)輸出到虛擬屏幕 然后可以獲取視頻的信息,指定輸出的位置等 |
| ImageReader | 這個類被允許直接從Surface接收渲染的圖像數(shù)據(jù) |
| MediaRecorder | 用于將音視頻編碼輸出 |
流程:
- 1.申請錄屏screenCaptureIntent
- 2.調(diào)用activity的 startActivityForResult(screenCaptureIntent,code);需要用戶允許
- 3.在onActivityResult獲取屏幕錄制的操作對象mMediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);
- 4.MediaProjection + VirtualDisplay + Surface(根據(jù)情況使用提供者) 實現(xiàn)錄屏截屏功能
使用:
1.在Activity的onCreate下創(chuàng)建
screenshotRecordUtil = new ScreenshotRecordUtil(); screenshotRecordUtil.screenCaptureIntent(this, new ScreenshotRecordUtil.ScreenshotRecordCallback() {@Overridepublic void onScreenshotSuccess(String path, Bitmap bitmap) {//path目前沒寫(沒有保存文件,有需求自行在ScreenshotRecordUtil里startCapture方法實現(xiàn)),//這里是直接獲取的bitmap顯示//在主線程更新UIrunOnUiThread(new Runnable() {@Overridepublic void run() {//Glide.with(Live2Activity.this).load(bitmap).into(image);}});}@Overridepublic void onScreenshotFailure() {//截圖失敗}@Overridepublic void onRecordStart() {//錄屏開始//LogUtils.d("錄屏開始:");}@Overridepublic void onRecordStop(String path) {//錄屏結(jié)束//LogUtils.d("錄屏結(jié)束:"+path);}});2.實現(xiàn)onActivityResult方法
@RequiresApi(api = Build.VERSION_CODES.O)@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == ScreenshotRecordUtil.REQUEST_SHOT_CODE && resultCode == RESULT_OK) {// 獲取申請截屏結(jié)果screenshotRecordUtil.setUpImageProjection(Live2Activity.this, resultCode, data);} else if (requestCode == ScreenshotRecordUtil.REQUEST_RECORD_CODE && resultCode == RESULT_OK) {// 獲取申請錄屏結(jié)果//錄屏文件存儲目錄地址String root = Environment.getExternalStorageDirectory() + AppConstants.PATH_VIDEO);File appDir = new File(root);if (!appDir.exists()) {appDir.mkdirs();}//創(chuàng)建文件File file = new File(appDir, System.currentTimeMillis() + ".mp4");screenshotRecordUtil.setUpVideoProjection(Live2Activity.this, resultCode, data, file);}}3.點擊按鈕,截屏
/*** 截取屏幕* REQUEST_SHOT_CODE 是請求碼,和你的重復(fù)了可以自己更改*/@OnClick(R.id.btn_screenshot)void screenshot() {screenshotRecordUtil.screenCapture(ScreenshotRecordUtil.REQUEST_SHOT_CODE);}4.點擊按鈕,錄屏
/*** 錄屏*/@OnClick(R.id.btn_recording)void onClickRecording() {if (screenshotRecordUtil.isRecording()) {screenshotRecordUtil.mediaRecorderStop();} else {screenshotRecordUtil.screenCapture(ScreenshotRecordUtil.REQUEST_RECORD_CODE);}}ScreenshotRecordUtil 類:
import static android.content.Context.WINDOW_SERVICE;import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.PixelFormat; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.media.Image; import android.media.ImageReader; import android.media.MediaRecorder; import android.media.projection.MediaProjection; import android.media.projection.MediaProjectionManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager;import com.blankj.utilcode.util.StringUtils; import com.blankj.utilcode.util.ThreadUtils;import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit;/*** 截屏錄屏工具* <p>* 1.申請錄屏Intent* <p>* 2.然后調(diào)用activity的 startActivityForResult(screenCaptureIntent,code);* <p>* 3.onActivityResult獲取屏幕錄制的操作對象* mMediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);* <p>* 4.MediaProjection + VirtualDisplay + Surface(根據(jù)情況使用提供者) 實現(xiàn)錄屏截屏功能*/ public class ScreenshotRecordUtil {private static final String TAG = ScreenshotRecordUtil.class.getSimpleName();public static final int REQUEST_SHOT_CODE = 10011;//截屏請求回調(diào)codepublic static final int REQUEST_RECORD_CODE = 10012;//錄屏請求回調(diào)codeprivate MediaRecorder mMediaRecorder; //MediaRecorder屏幕錄制 需求場景是把屏幕錄制成文件,錄屏直播則使用MediaCodec或者大名鼎鼎的FFmpegprivate ImageReader mImageReader; //獲取屏幕渲染得到Imageprivate MediaProjectionManager mediaProjectionManager; //系統(tǒng)提供的一個錄屏服務(wù)private MediaProjection mMediaProjection; //屏幕錄制的操作對象private VirtualDisplay mVirtualDisplay; //虛擬屏幕——VirtualDisplayprivate String mVideoPath; //錄像輸入地址private Activity activity;private Intent screenCaptureIntent;private ScreenshotRecordCallback screenshotRecordCallback;/*** 申請錄屏Intent*/public void screenCaptureIntent(Activity activity, ScreenshotRecordCallback screenshotRecordCallback) {this.activity = activity;this.screenshotRecordCallback = screenshotRecordCallback;this.mediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);this.screenCaptureIntent = mediaProjectionManager.createScreenCaptureIntent();}/*** 調(diào)用activity的 startActivityForResult*/public void screenCapture(int code) {this.activity.startActivityForResult(screenCaptureIntent, code);}/*** 獲取屏幕截圖** @param activity activity* @param resultCode onActivityResult返回的 resultCode* @param resultData onActivityResult返回的 resultData*/public void setUpImageProjection(Activity activity, int resultCode, Intent resultData) {//創(chuàng)建mImageReader,用于獲取VirtualDisplay的imageDisplayMetrics displayMetrics = new DisplayMetrics();WindowManager windowManager = (WindowManager) activity.getSystemService(WINDOW_SERVICE);windowManager.getDefaultDisplay().getMetrics(displayMetrics);int width = displayMetrics.widthPixels;int height = displayMetrics.heightPixels;Log.e(TAG, "displayMetrics width=" + width + ", height=" + height);this.mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);//獲取屏幕錄制的操作對象this.mMediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);//創(chuàng)建虛擬屏幕,使用ImageReader提供的Surface//VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR:當沒有內(nèi)容顯示時,允許將內(nèi)容鏡像到專用顯示器上。//VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY:僅顯示此屏幕的內(nèi)容,不鏡像顯示其他屏幕的內(nèi)容。//VIRTUAL_DISPLAY_FLAG_PRESENTATION:創(chuàng)建演示文稿的屏幕。//VIRTUAL_DISPLAY_FLAG_PUBLIC:創(chuàng)建公開的屏幕。//VIRTUAL_DISPLAY_FLAG_SECURE:創(chuàng)建一個安全的屏幕this.mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCapture",width, height,displayMetrics.densityDpi,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mImageReader.getSurface(), null, null);//這里稍稍作了個延時,立馬取的話 mImageReader.acquireLatestImage()可能為空ThreadUtils.executeByCachedWithDelay(new ThreadUtils.SimpleTask<Object>() {@Overridepublic Object doInBackground() throws Throwable {startCapture();return null;}@Overridepublic void onSuccess(Object result) {}}, 100, TimeUnit.MILLISECONDS);}/*** 屏幕錄制** @param activity activity* @param resultCode onActivityResult返回的 resultCode* @param resultData onActivityResult返回的 resultData* @param file 錄制輸出文件*/public void setUpVideoProjection(Activity activity, int resultCode, Intent resultData, File file) {//創(chuàng)建mImageReader,用于獲取VirtualDisplay的imageDisplayMetrics displayMetrics = new DisplayMetrics();WindowManager windowManager = (WindowManager) activity.getSystemService(WINDOW_SERVICE);windowManager.getDefaultDisplay().getMetrics(displayMetrics);int width = displayMetrics.widthPixels;int height = displayMetrics.heightPixels;Log.e(TAG, "displayMetrics width=" + width + ", height=" + height);initMediaRecorder(file, width, height);//獲取屏幕錄制的操作對象this.mMediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);//創(chuàng)建虛擬屏幕 需要在mMediaRecorder.prepare();后,否則mMediaRecorder.getSurface()拿不到Surface對象this.mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenRecorder",width, height,displayMetrics.densityDpi,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mMediaRecorder.getSurface(), null, null);mediaRecorderStars();}/*** 截圖*/public void startCapture() {String mImageName = System.currentTimeMillis() + ".png";Log.i(TAG, "image name is : " + mImageName);Image image = mImageReader.acquireLatestImage();if (image == null) {Log.e(TAG, "image is null.");if (screenshotRecordCallback != null) {screenshotRecordCallback.onScreenshotFailure();}return;}int width = image.getWidth();int height = image.getHeight();final Image.Plane[] planes = image.getPlanes();final ByteBuffer buffer = planes[0].getBuffer();int pixelStride = planes[0].getPixelStride();int rowStride = planes[0].getRowStride();int rowPadding = rowStride - pixelStride * width;Bitmap mBitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);mBitmap.copyPixelsFromBuffer(buffer);mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height);image.close();if (mBitmap != null) {// 保存或者顯示...if (screenshotRecordCallback != null) {screenshotRecordCallback.onScreenshotSuccess(null, mBitmap);}}}/*** 錄屏*/private void initMediaRecorder(File file, int width, int height) {this.mMediaRecorder = new MediaRecorder();// 設(shè)置音頻來源 需要動態(tài)申請 android.permission.RECORD_AUDIO 權(quán)限this.mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 設(shè)置視頻來源this.mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);// 設(shè)置輸出格式this.mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 設(shè)置輸出文件this.mVideoPath = file.getAbsolutePath();this.mMediaRecorder.setOutputFile(mVideoPath);// 設(shè)置視頻寬高this.mMediaRecorder.setVideoSize(width, height);// 設(shè)置視頻幀率this.mMediaRecorder.setVideoFrameRate(30);// 設(shè)置視頻編碼比特率this.mMediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);// 設(shè)置音頻編碼this.mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 設(shè)置視頻編碼this.mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);try {this.mMediaRecorder.prepare();} catch (IOException e) {e.printStackTrace();}}//通過mVideoPath地址確定是否在錄屏public boolean isRecording() {Log.e(TAG, "mVideoPath is " + mVideoPath + ",b:" + StringUtils.isEmpty(mVideoPath));return !StringUtils.isEmpty(mVideoPath);}//開始錄制public void mediaRecorderStars() {if (StringUtils.isEmpty(mVideoPath)) {Log.e(TAG, "mVideoPath is null");return;}if (mMediaRecorder == null) {Log.e(TAG, "mMediaRecorder is null");return;}mMediaRecorder.start();if (screenshotRecordCallback != null) {screenshotRecordCallback.onRecordStart();}}//結(jié)束錄制public void mediaRecorderStop() {if (mMediaRecorder != null) {mMediaRecorder.stop();if (screenshotRecordCallback != null) {screenshotRecordCallback.onRecordStop(mVideoPath);}mVideoPath = null;mMediaRecorder.reset();} else {Log.e(TAG, "mMediaRecorder is null");}}/*** 釋放相關(guān)資源*/public void release() {if (mImageReader != null) {mImageReader.close();}if (mMediaRecorder != null) {mMediaRecorder.setOnErrorListener(null);mMediaProjection.stop();mMediaRecorder.reset();mMediaRecorder.release();}if (mVirtualDisplay != null) {mVirtualDisplay.release();mVirtualDisplay = null;}if (mMediaProjection != null) {mMediaProjection.stop();mMediaProjection = null;}}public interface ScreenshotRecordCallback {void onScreenshotSuccess(String path, Bitmap bitmap);void onScreenshotFailure();void onRecordStart();void onRecordStop(String path);}為了向別人、向世界證明自己而努力拼搏,而一旦你真的取得了成績,才會明白:人無須向別人證明什么,只要你能超越自己。
總結(jié)
以上是生活随笔為你收集整理的简单屏幕录制截屏工具的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 元编程
- 下一篇: js和cs的值相互传递和函数的相互调用