Android截屏、錄屏工具

wallhaven-533030.jpg

顏色拾取器分析

有時候會用到顏色拾取器這樣的東西來查看屏幕上的顏色值,一直是用Pixolor這個軟件來看顏色的;很方便,點(diǎn)哪里顯示哪里,也沒有延遲,以為是什么黑科技;我注意到一個細(xì)節(jié),如果只是切換屏幕,顏色拾取器不會更新,只有移動拾取器才更新選中;可以確定是截屏來實(shí)現(xiàn)的了,那就簡單了,截屏獲取像素點(diǎn)的顏色值就好了

錄屏和截屏

網(wǎng)上看了一下,截屏大概分為保存View為圖像和調(diào)用錄屏服務(wù)兩種辦法,錄屏是比較好的辦法,可以在APP外截屏,所以簡單的封裝了一下

集成方法:

Step 1. Add the JitPack repository to your build file

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

Step 2. Add the dependency

dependencies {
            implementation 'com.github.tyhjh:ScreenShot:v1.0.1'
    }

截屏

簡單使用

主要分為兩步,第一步是開啟錄屏;第二步就可以直接獲取截屏,返回Bitmap
截圖的過程錄屏是開啟的,錄屏開啟就可以進(jìn)行截屏,操作完需要關(guān)閉錄屏
截屏過程很快,效果很好

//第一次會自動申請錄屏權(quán)限
ScreenRecordUtil.getInstance().screenShot(this, new OnScreenShotListener() {
            @Override
            public void screenShot() {
            //可以獲取截圖,可以多次調(diào)用
            iv_pre.setImageBitmap(ScreenRecordUtil.getInstance().getScreenShot());
            //最后關(guān)閉錄屏服務(wù)
            ScreenRecordUtil.getInstance().destroy();
            }
        });

如果是APP外截屏則開啟懸浮窗服務(wù),可以通過操作懸浮窗進(jìn)行截屏
參考文章:Android 截屏方式整理Android錄屏(5.0+)

截屏實(shí)現(xiàn)代碼

1.初始化一個MediaProjectionManager

MediaProjectionManager mMediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);

2.創(chuàng)建并啟動Intent

startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(),REQUEST_MEDIA_PROJECTION);

3.在onActivityResult中拿到MediaProjection

mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);

4.設(shè)置VirtualDisplay將圖像和展示的View關(guān)聯(lián)起來。一般來說我們會將圖像展示到SurfaceView,這里為了為了便于拿到截圖,我們使用ImageReader,他內(nèi)置有SurfaceView。

mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
mScreenWidth, mScreenHeight, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);

5.通過ImageReader拿到截圖

Image image = null;
image = mImageReader.acquireLatestImage();
while (image == null) {
    SystemClock.sleep(10);
    image = mImageReader.acquireLatestImage();
}
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);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
image.close();
return bitmap;

6.注意截屏之后要及時關(guān)閉VirtualDisplay ,因?yàn)閂irtualDisplay 是十分消耗內(nèi)存和電量的。

if (mVirtualDisplay == null) {
            return;
}
mVirtualDisplay.release();
mVirtualDisplay = null;

錄屏

簡單使用

錄屏和截屏差不多,只是截屏的時候只是設(shè)置了一個ImageReader去獲取圖像數(shù)據(jù),而錄屏是設(shè)置一個SurfaceView去接收內(nèi)容,獲取視頻流,然后通過MediaCodec來實(shí)現(xiàn)視頻的硬編碼,然后保存為視頻文件

v2-24d825761d500ae9a0bf42e4c7a32c88_hd.png-69.3kB
v2-24d825761d500ae9a0bf42e4c7a32c88_hd.png-69.3kB

初始化錄屏的大小和碼率

//碼率為32M
private int screenRecordBitrate = 32 * 1024 * 1024;

ScreenRecordUtil.getInstance().init(ScreenUtil.SCREEN_WIDTH, ScreenUtil.SCREEN_HEIGHT, screenRecordBitrate);

開始錄屏,設(shè)置輸出文件

String savePath = MyApplication.baseDir + System.currentTimeMillis() + ".mp4";
//開始錄屏
ScreenRecordUtil.getInstance().start(MainActivity.this, savePath);

停止錄屏

new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(60 * 1000);
                    //結(jié)束錄屏
                   ScreenRecordUtil.getInstance().destroy();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

錄屏具體實(shí)現(xiàn)

參考文章:Android視頻錄制--屏幕錄制

1.在 AndroidManifest 中添加權(quán)限,Android 6.0 加入的動態(tài)權(quán)限申請,如果應(yīng)用的 targetSdkVersion 是 23,申請敏感權(quán)限還需要動態(tài)申請

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

中間操作和截屏一樣,就是準(zhǔn)備開啟錄屏

5.創(chuàng)建虛擬屏幕,這一步就是通過 MediaProject 錄制屏幕的關(guān)鍵所在,VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 參數(shù)是指創(chuàng)建屏幕鏡像,所以我們實(shí)際錄制內(nèi)容的是屏幕鏡像,但內(nèi)容和實(shí)際屏幕是一樣的,并且這里我們把 VirtualDisplay 的渲染目標(biāo) Surface 設(shè)置為 MediaRecordergetSurface,后面我就可以通過 MediaRecorder 將屏幕內(nèi)容錄制下來,并且存成 video 文件

private void createVirtualDisplay() {
  virtualDisplay = mediaProjection.createVirtualDisplay(
        "MainScreen",
        width,
        height,
        dpi,
        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
        mediaRecorder.getSurface(),
        null, null);
}

6.錄制屏幕數(shù)據(jù),這里利用 MediaRecord 將屏幕內(nèi)容保存下來

private void initRecorder() {
  File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".mp4");
  mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
  mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
  mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
  mediaRecorder.setOutputFile(file.getAbsolutePath());
  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();
  }
}

public boolean startRecord() {
  if (mediaProjection == null || running) {
    return false;
  }
  initRecorder();
  createVirtualDisplay();
  mediaRecorder.start();
  running = true;
  return true;
}

項(xiàng)目地址:https://github.com/tyhjh/ScreenShot

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容