Android实现全局截图以及录屏

来源:互联网 发布:薛之谦的淘宝店经验 编辑:程序博客网 时间:2024/05/17 13:07

废话不多说 直接上代码(使用kotlin编写大致与java差不多) 代码注释也挺详细的

利用mediaProjection 实现截屏与录屏
mediaProjection 是android 5.0 加入的一个 主要用户捕捉屏幕的东西

createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, VirtualDisplay.Callback callback, Handler handler)//创建一个VirtualDisplay捕获屏幕的内容。//捕捉到的内容将写入到传入的surface中//因此可将传入MediaRecorder以及ImageReader中的surface 并 通过他们取出surface进行截图与录制
class ScreenCapture constructor(private val width : Int ,private  val height : Int ){    private var mImageReader : ImageReader = ImageReader.newInstance(width,height, PixelFormat.RGBA_8888,3)    private var mediaProjectionManager = App.app.mediaProjectionManager    //初始化截图功能    fun startCapture(resultCode : Int, data : Intent?) {        val mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data)        mediaProjection.createVirtualDisplay("capture",width,height,1,                DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,                mImageReader.surface,null,null)    }    fun acquire() : Bitmap?{        var image: Image? = null        //当未开始录制的时候先调用此方法会报错        //java.lang.IllegalStateException: mImageReader.acquireLatestImage() must not be null        try {            image = mImageReader.acquireLatestImage()            //此高度和宽度似乎与ImageReader构造方法中的高和宽一致            val iWidth = image.width            val iHeight = image.height            //panles的数量与图片的格式有关            val plane = image.planes[0]            val bytebuffer = plane.buffer            //计算偏移量            val pixelStride = plane.pixelStride            val rowStride = plane.rowStride;            val rowPadding = rowStride - pixelStride * iWidth;            val bitmap = Bitmap.createBitmap(iWidth + rowPadding / pixelStride,             iHeight, Bitmap.Config.ARGB_8888);            bitmap.copyPixelsFromBuffer(bytebuffer)            //必须要有这一步,不如图片会有黑边            return Bitmap.createBitmap(bitmap,0,0,iWidth,iHeight)        }catch (e : Exception){            e.printStackTrace()            return null        }finally {            image?.close()        }    }}
   class MainActivity : PermissionCompatActivity(), MainContract.View {    //截屏图片大小设置    val width = 1440    val height = 2560    var capturor: ScreenCapture = ScreenCapture(width, height)    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        //启动MediaProjection并准备截图        startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), 1)        imageView.setOnClickListener {            imageView.setImageBitmap(capturor.acquire())        }    }    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {        //截屏前的准备        capturor.startCapture(resultCode,data)    }}

拼命截图放入同一个ImageView中的结果
这里写图片描述

屏幕录制需要的权限
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO

class ScreenRecorder(private val width: Int, private val height: Int, val outputFile: String) {    private val mRecorder = MediaRecorder()    private val mediaProjectionManager = App.app.mediaProjectionManager    //初始化Recorder    init {        prepare()    }    private fun prepare() {        with(mRecorder) {            setAudioSource(MediaRecorder.AudioSource.MIC)            setVideoSource(MediaRecorder.VideoSource.SURFACE)            setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)            setVideoEncoder(MediaRecorder.VideoEncoder.H264)            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)            //帧率 帧数简单地说,帧数就是在1秒钟时间里传输的图片的帧数,            // 也可以理解为图形处理器每秒钟能够刷新几次,通常用fps(Frames Per Second)表示。            setVideoFrameRate(30)            //码率 码率:影响体积,与体积成正比:码率越大,体积越大;码率越小,体积越小。            //码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒。也就是取样率            setVideoEncodingBitRate(500 * 1000)            setOutputFile(outputFile)            //设置输出目录            val display = App.app.windowManager.defaultDisplay            val dm = DisplayMetrics()            display.getMetrics(dm)            setVideoSize(width, height)            prepare()        }    }    fun startRecord(resultCode: Int, data: Intent?) {        val mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data) ?: return        //如果无法获取mediaProjection 则返回        mediaProjection.createVirtualDisplay("test", width, height, 1,                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mRecorder.surface, null, null)        mRecorder.start()    }    fun stopRecord() {        Thread {            //避免录制时间过短而报错            Thread.sleep(1000)            mRecorder.stop()        }.start()    }}
class MainActivity : PermissionCompatActivity(), MainContract.View {    val width = 1440    val height = 2560    val mRecorder = ScreenRecorder(width, height, outputFile = Environment.getExternalStorageDirectory().path + "/output.mp4")    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        //开始的同时开始录制        startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), 1)        imageView.setOnClickListener {            mRecorder.stopRecord()        }    }    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {        //开始录制        mRecorder.startRecord(resultCode,data)    }}
原创粉丝点击