问题

在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下载

github

更多相关文章

  1. android edittext操作
  2. 如何运行 .smali 程序
  3. New Gingerbread API: StrictMode阅读笔记
  4. eclipse 单步调试JNI
  5. Android(安卓)开发之 View.post() 的作用
  6. 彩信对象android(5)_发彩信操作
  7. Android利用百度地图定位
  8. 在mac上快速搭建Android、iOS自动打包环境(一)
  9. AlarmManager全局定时器/闹钟

随机推荐

  1. 关于资源文件:颜色
  2. android中的广播接收器
  3. 解决Error:Android(安卓)Dex: com.androi
  4. android的软键盘的enter键的替换
  5. std::to_string is not memember of std
  6. Android打印工具类
  7. android官网demo之异步加载图片
  8. Android(安卓)- ToDoList(fragment) 详解
  9. Windows环境下Android(安卓)Studio v1.0
  10. 查看安卓(Android)设备处理器(CPU)架构(A