Android5.0免Root截屏,录屏
2017-09-11 15:30
351 查看
http://blog.csdn.net/wds1181977/article/details/52174840
接着调用MediaProjectionManager.createScreenCaptureIntent()弹出dialog询问用户是否授权应用捕捉屏幕,同时覆写onActivityResult()获取授权结果。
如果授权成功,通过MediaProjectionManager.getMediaProjection(int resultCode, Intent resultData)获取MediaProjection实例,通过MediaProjection.createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, VirtualDisplay.Callback callback, Handler handler)创建VirtualDisplay实例。实际上在上述方法中传入的surface参数,是真正用来截屏或者录屏的。
Android视频录制
Android 5.0截屏
Android录屏代码
本文Demo
MediaProjection介绍
MediaProjection可以用来捕捉屏幕,具体来说可以截取当前屏幕和录制屏幕视频。MediaProjection由MediaProjectionManager来管理和获取。使用步骤
首先获取MediaProjectionManager,和其他的Manager一样通过 Context.getSystemService() 传入参数MEDIA_PROJECTION_SERVICE获得实例。接着调用MediaProjectionManager.createScreenCaptureIntent()弹出dialog询问用户是否授权应用捕捉屏幕,同时覆写onActivityResult()获取授权结果。
如果授权成功,通过MediaProjectionManager.getMediaProjection(int resultCode, Intent resultData)获取MediaProjection实例,通过MediaProjection.createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, VirtualDisplay.Callback callback, Handler handler)创建VirtualDisplay实例。实际上在上述方法中传入的surface参数,是真正用来截屏或者录屏的。
截屏
截屏这里用到ImageReader类,这个类的getSurface()方法获取到surface直接传入MediaProjection.createVirtualDisplay()方法中,此时就可以执行截取。通过ImageReader.acquireLatestImage()方法即可获取当前屏幕的Image,经过简单处理之后即可保存为Bitmap。private void startCapture() { mImageName = System.currentTimeMillis() + ".png"; Log.e(TAG, "image name is : " + mImageName); Image 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(); if (bitmap != null) { Log.e(TAG, "bitmap create success "); try { File fileFolder = new File(mImagePath); if (!fileFolder.exists()) fileFolder.mkdirs(); File file = new File(mImagePath, mImageName); if (!file.exists()) { Log.e(TAG, "file create success "); file.createNewFile(); } FileOutputStream out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); out.close(); Log.e(TAG, "file save success "); Toast.makeText(this.getApplicationContext(), "截图成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { Log.e(TAG, e.toString()); e.printStackTrace(); } } }
录屏
录屏需要用到上篇博文中的MediaCadec,这个类将原始的屏幕数据编码,在通过MediaMuxer分装为mp4格式保存。MediaCodec.createInputSurface()获取一个surface对象讲起传入MediaProjection.createVirtualDisplay()即可获取屏幕原始多媒体数据,之后读取MediaCodec编码输出数据经过MediaMuxer封装处理为mp4即可播放,实现录屏。private void recordVirtualDisplay() {//循环多去编解码器输出数据经过处理保存为mp4 while (!mIsQuit.get()) { int index = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 10000); Log.i(TAG, "dequeue output buffer index=" + index); if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {//后续输出格式变化 resetOutputFormat(); } else if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {//请求超时 Log.d(TAG, "retrieving buffers time out!"); try { // wait 10ms Thread.sleep(10); } catch (InterruptedException e) { } } else if (index >= 0) {//有效输出 if (!mMuxerStarted) { throw new IllegalStateException("MediaMuxer dose not call addTrack(format) "); } encodeToVideoTrack(index); mMediaCodec.releaseOutputBuffer(index, false); } } } private void encodeToVideoTrack(int index) {//输出数据为mp4文件 ByteBuffer encodedData = mMediaCodec.getOutputBuffer(index); if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {//是特定格式信息等配置数据,不是媒体数据 // The codec config data was pulled out and fed to the muxer when we got // the INFO_OUTPUT_FORMAT_CHANGED status. // Ignore it. Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG"); mBufferInfo.size = 0; } if (mBufferInfo.size == 0) { Log.d(TAG, "info.size == 0, drop it."); encodedData = null; } else { Log.d(TAG, "got buffer, info: size=" + mBufferInfo.size + ", presentationTimeUs=" + mBufferInfo.presentationTimeUs + ", offset=" + mBufferInfo.offset); } if (encodedData != null) {//存在编码数据 encodedData.position(mBufferInfo.offset); encodedData.limit(mBufferInfo.offset + mBufferInfo.size); mMuxer.writeSampleData(mVideoTrackIndex, encodedData, mBufferInfo);//写入 Log.i(TAG, "sent " + mBufferInfo.size + " bytes to muxer..."); } } private void resetOutputFormat() { // should happen before receiving buffers, and should only happen once if (mMuxerStarted) { throw new IllegalStateException("output format already changed!"); } MediaFormat newFormat = mMediaCodec.getOutputFormat(); Log.i(TAG, "output format changed.\n new format: " + newFormat.toString()); mVideoTrackIndex = mMuxer.addTrack(newFormat); mMuxer.start(); mMuxerStarted = true; Log.i(TAG, "started media muxer, videoIndex=" + mVideoTrackIndex); }
附录参考
官方文档Android视频录制
Android 5.0截屏
Android录屏代码
本文Demo
相关文章推荐
- Android5.0免Root截屏,录屏
- Android5.0免Root截屏,录屏
- Android 截屏到桌面的最佳处理方案-无须ROOT-适用Android 8.0
- IOS之录屏截屏
- android5.0以上实现录屏功能,并将录屏内容在相册中显示!(unity调用android方法)
- 谁说 Android 手机一定要 root 权限才能截屏?![转]
- Android5.0录屏方案
- Android截屏和录屏Demo
- adb 截屏和录屏命令
- Unity 截屏 录屏 的方法参考
- (024)[工具软件]截屏录屏软件FSCapture(转)
- Unity 截屏 录屏 并且保存到 iOS相册
- Android5.0以上版本录屏实现代码(完整代码)
- nexus5 android5.0 型号LRX210 ROOT
- 接入金融理财H5活动遇到的问题备忘(防截屏,检查ROOT,金融理财h5安全,混淆不回调)
- Android Multimedia框架总结(二十五)MediaProjection实现手机截屏(无须root)
- 给大家推荐一款小巧简单功能齐全的截屏录屏软件--FSCapture
- 推荐-截屏录屏方法汇总
- Android5.0屏幕截屏与屏幕录制
- [置顶] Android Multimedia框架总结(二十五)MediaProjection实现手机截屏(无须root)