android視訊截圖&手機錄屏實現
問題
在android中有時候我們需要對螢幕進行截圖操作,單一的截圖操作好解決可以通過activity的頂層view DecorView獲取一個bitmap,得到就是當前activity上面的全部檢視。
View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); DisplayMetrics dm = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(dm); Bitmap ret = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels); view.destroyDrawingCache();
如果activity中包含一些視訊播放器比如SurfaceView GLSurfaceView
TextureView,在呼叫截圖程式碼會發現播放視訊的部分是黑屏的,原因是這幾種視訊渲染的view通過以上程式碼拿到的是緩衝區不是真正的影象。
解決辦法
android5.0以上系統提供了一個 MediaProjectionManager
類來對手機進行錄屏操作,也支援獲取手機的Image影象的操作,知道了這些我們就可以通過提供的api來進行截圖操作了。
這裡通過Service來操作截圖和錄屏的api
1.繫結截圖的Service
Intent intent = new Intent(this, ScreenService.class); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); public void onServiceConnected(ComponentName className, IBinder service) { DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); ScreenService.RecordBinder binder = (ScreenService.RecordBinder) service; recordService = binder.getRecordService(); recordService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi); mButton.setEnabled(true); mButton.setText(recordService.isRunning() ? "結束" : "開始"); }
2.請求許可權 onActivityResult 方法中回撥。
Intent captureIntent = projectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
成功後 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) { //######## 截圖邏輯 ######## mediaProjection = projectionManager.getMediaProjection(resultCode, data); recordService.setMediaProject(mediaProjection); recordService.initImageReader(); } }
3. 獲取截圖
@Override
public void onClick(View view) {
//######## 截圖邏輯 ########
Bitmap bitmap = recordService.getBitmap();
mImageView.setImageBitmap(bitmap);
}
錄屏
錄屏需要初始化一些錄屏引數,輸入麥克風型別視訊型別,儲存路徑等
private void initRecorder() {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(
getSavePath() + System.currentTimeMillis() + ".mp4");
mediaRecorder.setVideoSize(width, height);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
mediaRecorder.setVideoFrameRate(30);
try {
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
開始錄屏
mediaRecorder.start();
儲存路徑
完整Service程式碼
public class ScreenService extends Service {
private MediaRecorder mediaRecorder;
private VirtualDisplay virtualDisplay;
private boolean running;
private int width = 720;
private int height = 1080;
private int dpi;
private ImageReader mImageReader;
private MediaProjection mediaProjection;
@Override
public IBinder onBind(Intent intent) {
return new RecordBinder();
}
@Override
public void onCreate() {
super.onCreate();
running = false;
mediaRecorder = new MediaRecorder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
public void setMediaProject(MediaProjection project) {
mediaProjection = project;
}
public boolean isRunning() {
return running;
}
public void setConfig(int width, int height, int dpi) {
this.width = width;
this.height = height;
this.dpi = dpi;
}
/**
* 開始錄屏
*
* @return true
*/
public boolean startRecord() {
if (mediaProjection == null || running) {
return false;
}
initRecorder();
createVirtualDisplay();
mediaRecorder.start();
running = true;
return true;
}
/**
* 結束錄屏
*
* @return true
*/
public boolean stopRecord() {
if (!running) {
return false;
}
running = false;
mediaRecorder.stop();
mediaRecorder.reset();
virtualDisplay.release();
mediaProjection.stop();
return true;
}
public void setMediaProjection(MediaProjection mediaProjection) {
this.mediaProjection = mediaProjection;
}
/**
* 初始化ImageRead引數
*/
public void initImageReader() {
if (mImageReader == null) {
int maxImages = 2;
mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, maxImages);
createImageVirtualDisplay();
}
}
/**
* 建立一個錄屏 Virtual
*/
private void createVirtualDisplay() {
virtualDisplay = mediaProjection
.createVirtualDisplay("mediaprojection", width, height, dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder
.getSurface(), null, null);
}
/**
* 建立一個ImageReader Virtual
*/
private void createImageVirtualDisplay() {
virtualDisplay = mediaProjection
.createVirtualDisplay("mediaprojection", width, height, dpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader
.getSurface(), null, null);
}
/**
* 初始化儲存螢幕錄影的引數
*/
private void initRecorder() {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(
getSavePath() + System.currentTimeMillis() + ".mp4");
mediaRecorder.setVideoSize(width, height);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
mediaRecorder.setVideoFrameRate(30);
try {
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 獲取一個儲存螢幕錄影的路徑
*
* @return path
*/
public String getSavePath() {
if (Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) {
String rootDir = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/" +
"ScreenRecord" + "/";
File file = new File(rootDir);
if (!file.exists()) {
if (!file.mkdirs()) {
return null;
}
}
return rootDir;
} else {
return null;
}
}
/**
* 請求完許可權後馬上獲取有可能為null,可以通過判斷is null來重複獲取。
*/
public Bitmap getBitmap() {
Bitmap bitmap = cutoutFrame();
if (bitmap == null) {
getBitmap();
}
return bitmap;
}
/**
* 通過底層來獲取下一幀的影象
*
* @return bitmap
*/
public Bitmap cutoutFrame() {
Image image = mImageReader.acquireLatestImage();
if (image == null) {
return null;
}
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 bitmap = Bitmap.createBitmap(width +
rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
return Bitmap.createBitmap(bitmap, 0, 0, width, height);
}
public class RecordBinder extends Binder {
public ScreenService getRecordService() {
return ScreenService.this;
}
}
demo下載
相關推薦
android視訊截圖&手機錄屏實現
問題 在android中有時候我們需要對螢幕進行截圖操作,單一的截圖操作好解決可以通過activity的頂層view DecorView獲取一個bitmap,得到就是當前activity上面的全部檢視。 View view = activity.getWindow().getDecorView();
android手機截圖、錄屏
1. 手動截圖,通過其他第三方軟體傳送截圖,或者從手機取出截圖 2. 使用命令截圖,將截圖儲存到手機,再拉取到電腦 #!/bin/sh #執行 sh screenshot name picName=$1 filePath='caps' if [ ! $picName ];then picName=
Android實現全域性截圖以及錄屏
廢話不多說 直接上程式碼(使用kotlin編寫大致與java差不多) 程式碼註釋也挺詳細的 利用mediaProjection 實現截圖與錄屏 mediaProjection 是android 5.
FastStone Capture 輕便而強大的截圖、錄屏軟體
這款軟體具有:截圖、螢幕錄製、取色、螢幕放大器、螢幕焦點、螢幕十字線等功能,並且在截圖後還可以編輯圖片! 檔案小巧,功能卻十分齊全,可謂是麻雀雖小五臟俱全!強烈推薦。 1、下載 百度網盤(已破解+已漢化+無需安裝直接執行):https://pan.字baidu.去com/掉s/1JWqgVNEmYdAs
gnome中截圖與錄屏操作
截圖與錄屏 你可以抓取當前螢幕圖片(截圖)或者錄製一個當前螢幕中操作的視訊(錄屏)。當你想要給某人演示怎樣在電腦上進行某些操作時,你可以通過截圖和錄屏來獲取圖片及視訊檔案,然後通過 email 向別人傳送這些檔案或將這些檔案共享到網路上。 截圖
Ubuntu 截圖與錄屏
Ubuntu 截圖 Ubuntu17.04自帶有截圖軟體和截圖快捷鍵,可以滿足正常截圖試用。在dash裡面直接輸入jie,第一個即是截圖軟體,開啟如下圖,執行比較穩定。 截全屏通用快捷鍵PrintScreen,按下後如下圖所示 以上截圖預設儲存到 /使用者/圖片/目錄下。
Android 拍照 截圖 事件監聽實現
需求是獲得使用者截圖,或者拍照的主動存圖行為。 但是 android 官方沒有提供回撥廣播之類的實現監聽,所以需要用另一種方式達到需求,這裡實現的就是通過監聽media資料夾實現目的。 所需許可權: <uses-permission android:name="an
adb命令截圖和錄屏
錄屏 adb shell screenrecord /sdcard/test01.mp4 adb pull /sdcard/test01.mp4 截圖 adb shell screencap -p /sdcard/screen.png adb pull /sdc
Cypress系列(60)- 執行時的截圖和錄屏
如果想從頭學起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 背景 在測試執行時截圖和錄屏能夠在測試錯誤時快速定位到問題所在 Cypress 截圖和錄屏功能強大 無須配置,自動截圖
Android Multimedia實戰(四)MediaProjection實現截圖,與MediaMuxer實現錄屏為MP4,Gif格式
MediaProjection可以用來捕捉螢幕,具體來說可以擷取當前螢幕和錄製螢幕視訊 (5.0以上) 先總結下系統是如何實現組合鍵截圖的: 都應該知道Android原始碼中對按鍵的捕獲位於檔案PhoneWindowManager.java中 當滿足按鍵
Ruby+appium實現截圖、滑屏、長按、日誌輸出到本地文件夾
username 實例 方法 pytho 日誌 用戶名 read 清除 文件夾 require ‘rubygems‘ require ‘appium_lib‘require ‘date‘require ‘logger‘require ‘pathname‘require ‘t
js+html手機端視訊截圖
在執行這段程式碼的時候引用的視訊一定要儲存在本地,否則會報canvas.toDataURL()錯 <html> <meta http-equiv="X-UA-Compatible" content="chrome=1"> <head>
C++實現螢幕截圖(全屏截圖)
最近維護的專案,在某些情況下,光有日誌還不行,於是添加了截圖功能,特定情況下,會自動截圖,輔助分析,從而改程序序。以下是截圖實現程式碼。 void CDemoDlg::ScreenShot(void) { CWnd *pDesktop = GetDesktopWi
Android手機錄屏並製作Gif
做效果展示時經常需要一些Gif圖來顯示動態效果,我目前使用的方法是手機錄屏生成視訊檔案,再通過第三方軟體用視訊檔案生成動圖。剛才製作了一個動圖效果圖如下: 這裡我使用的是adb的screenrecord命令,它是API Level 19以上才支援的,官方文
canvas與html5實現視訊截圖功能
這段時間一直在研究canvas,突發奇想想做一個可以截圖視訊的功能,然後把圖片拉去做表情包,哈哈哈哈哈哈~~ 製作方法: 1.在頁面中載入視訊 在使用canvas製作這個截圖功能時,首先必須保證頁面上已經載入完成了這個視訊,這樣才能夠方便的對其操作。如果使用下面直接
android後臺截圖實現(2)--screencap原始碼修改
首先找到screencap類在Android原始碼中的位置,/442/frameworks/base/cmds/screencap/screencap.cpp。 原始碼如下: /* * Copyright (C) 2010 The Android Op
html5視訊截圖實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content
Android系統截圖的實現(附程式碼)
1.背景 寫部落格快兩年了,寫了100+的文章,最火的文章也是大家最關注的就是如何實現android系統截圖。其實我們google android_screen_shot就會找到很對
通過Python連線手機,並截圖手機螢幕儲存到電腦(android)
首先下載adb可以到百度網盤連結下載:https://pan.baidu.com/s/1htbYtq0或者自己去搜索引擎搜尋,網上一大堆將下載的壓縮包解壓,如圖:然後再系統中新增環境變數:右鍵我的電腦- 屬性-高階系統設定-高階-環境變數將Path中新增adb.exe的路徑:
Ruby+appium實現截圖、滑屏、長按、日誌輸出到本地資料夾
require 'rubygems' require 'appium_lib' require 'date' require 'logger' require 'pathname' require 'thread' require"fileutils" capa