软件编程
位置:首页>> 软件编程>> Android编程>> Android实现截屏功能

Android实现截屏功能

作者:爱乐写代码  发布时间:2022-10-25 04:36:52 

标签:Android,截屏

导言

目前截屏的方法很多,root不适用,要么其他方法就是有局限性,而其中官方给出的方案最好—MediaProjection

介绍

Android 5.0以后开放的录屏API,取视频中的一帧数据,这样就可以实现截屏

步骤

在activity中授权,在service中完成初始化并截图,当然可以后台定时截图,但是6.0系统会有内存溢出的bug

1:build.gradle


compileSdkVersion 21
   buildToolsVersion '27.0.3'

defaultConfig {
       applicationId "com.aile.screenshot"
       multiDexEnabled true
       minSdkVersion 21
       targetSdkVersion 21
       versionCode 1
       versionName "1.0"
   }

2:在activity中授权


public void requestCapturePermission() {
       if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
           return;
       }
       MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
       startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
   }

@Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);
       switch (requestCode) {
           case REQUEST_MEDIA_PROJECTION:
               if (resultCode == RESULT_OK && data != null) {
                   Service.setResultData(data);
                   startService(new Intent(this, Service.class));
                   finish();
               }
               break;
       }
   }

3:在service中初始化ImageReader,MediaProjection


private void createImageReader() {
       mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1);
   }
public void setUpMediaProjection() {
       mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
       }
   }

4:在service中完成截图重要步骤:


private void startScreenShot() {
       Handler handler = new Handler();
       handler.postDelayed(new Runnable() {
           @Override
           public void run() {
               startVirtual();
           }
       }, 0);

handler.postDelayed(new Runnable() {
           @Override
           public void run() {
               startCapture();
           }
       }, 50);
   }
public void startVirtual() {
       if (mMediaProjection != null) {
           virtualDisplay();
       } else {
           setUpMediaProjection();
           virtualDisplay();
       }
   }
private void virtualDisplay() {
       mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
               mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
               mImageReader.getSurface(), null, null);
   }

//异常处理的核心
private void startCapture() {
       Image image = null;
       try {
           image = mImageReader.acquireLatestImage();
       } catch (IllegalStateException e) {
           if (null != image) {
               image.close();
               image = null;
               image = mImageReader.acquireLatestImage();
           }
       }
       if (image == null) {
           startScreenShot();
       } else {
           SaveTask mSaveTask = new SaveTask();
           AsyncTaskCompat.executeParallel(mSaveTask, image);

new Handler().postDelayed(new Runnable() {
               @Override
               public void run() {
                   stopVirtual();
                   tearDownMediaProjection();
               }
           }, 0);
       }
   }
public class SaveTask extends AsyncTask<Image, Void, Bitmap> {
       @Override
       protected Bitmap doInBackground(Image... params) {
           if (params == null || params.length < 1 || params[0] == null) {
               return null;
           }
           Image image = params[0];
           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;
       }

@Override
       protected void onPostExecute(final Bitmap bitmap) {
           super.onPostExecute(bitmap);
           //处理bitmap的业务代码
   }

5:Bitmap转IS流,指定区域截图


// 将Bitmap转换成InputStream
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
  InputStream inputStream = new ByteArrayInputStream(bos.toByteArray());
//指定区域截图
  Rect mRect = new Rect(51, 74, 58, 62);
  BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, true);
  Bitmap bm = bitmapRegionDecoder.decodeRegion(mRect, null);

6:定时任务的处理


private Timer timer = new Timer();
public void shootByTime() {
       final Handler handler = new Handler() {
           @Override
           public void handleMessage(Message msg) {
               startScreenShot();
               super.handleMessage(msg);
           }
       };
       timer.schedule(new TimerTask() {
           @Override
           public void run() {
               Message message = new Message();
               message.what = 1;
               handler.sendMessage(message);
           }
       }, 0, 100);
   }

7:横竖屏的处理


@Override
   public void onConfigurationChanged(Configuration newConfig) {
       super.onConfigurationChanged(newConfig);
       if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_PORTRAIT) {
           mRect = new Rect(51, 775, 745, 47);
       } else if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_LANDSCAPE) {
           mRect = new Rect(54, 24, 545, 45);
       }
   }

8:还有很多,只需按照需求走就OK,没有难的东西,需要不停的学习和积累

来源:https://blog.csdn.net/ware00/article/details/80744465

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com