「Android」后盾截屏的初步实现

须要明确,在Android中,如果只是想得到正在运行的应用程序本身的界面,是非常简单的,只须要基于View对象即可实现截屏个性,具体此处不再赘述。但如果是想从后盾服务中实时的截屏,获取除了应用程序本身以外的其余界面,则须要依赖于MediaProjectionManager类。

以下为后盾截屏的简略步骤和对应代码:

  • 新建通明Activity
  • 启动截屏Service

新建通明Activity

首先,新建一个通明Activity(新建通明Activity的次要起因是,startActivityForResult()办法为Activity类的对象办法,必须得有一个Activity作为“母体”),并在在这个Activity中调用requestCaptureScreen()办法,在该办法中初始化了若干截屏相干数值并通过createScreenCaptureIntent())办法向用户发动截屏申请:

    private void requestCaptureScreen() {        Log.d(TAG, "requestCaptureScreen: ");        Display display = this.getWindowManager().getDefaultDisplay();        DisplayMetrics metrics = new DisplayMetrics();        display.getMetrics(metrics);        mWidth = metrics.widthPixels;        mHeight = metrics.heightPixels;        mDpi = metrics.densityDpi;        mMediaProjectionManager = (MediaProjectionManager) this.getSystemService(Context.MEDIA_PROJECTION_SERVICE);        if (mMediaProjectionManager != null) {            // 要害代码            this.startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);        }    }

在调用startActivityForResult()办法后,须要重写onActivityResult()办法,在该办法中当确认获取到用户受权后,启动截屏Service:

    @SuppressLint("WrongConstant")    @Override    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {        Log.d(TAG, "onActivityResult: InvisibleActivity");        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {            Intent service = new Intent(this, ScreenShotService.class);            service.putExtra("resultCode", resultCode);            service.putExtra("data", data);            service.putExtra("mWidth", mWidth);            service.putExtra("mHeight", mHeight);            service.putExtra("mDpi", mDpi);            startForegroundService(service);        }    }

启动截屏Service

在截屏Service启动后,别离获取到MediaProjectionManager对象和MediaProjection对象,并调用captureScreen()办法开始截屏并获取截屏文件的门路:

    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.d(TAG, "onStartCommand: ScreenShotService");        createNotificationChannel();        int resultCode = intent.getIntExtra("resultCode", 0);        Intent data = intent.getParcelableExtra("data");        int width = intent.getIntExtra("mWidth", 0);        int height = intent.getIntExtra("mHeight", 0);        int dpi = intent.getIntExtra("mDpi", 0);        MediaProjectionManager mediaProjectionManager =            (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);        MediaProjection projection = mediaProjectionManager.getMediaProjection(resultCode, data);        // 获取截屏文件的门路        String filePath = captureScreen(projection, width, height, dpi, this);        return super.onStartCommand(intent, flags, startId);    }
    /**     * 获取截屏     *     * @param projection projection     * @param width width     * @param height height     * @param dpi dpi     * @param context context     * @return 返回截屏文件门路     */    public static String captureScreen(MediaProjection projection, int width, int height, int dpi, Context context) {        Log.d(TAG, "screenShot: ");        Bitmap bitmap = null;        // 获取ImageReader实例        @SuppressLint("WrongConstant")        ImageReader imageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);        // 获取虚构显示器VirtualDisplay的实例        VirtualDisplay display = projection.createVirtualDisplay("ScreenShot", width, height, dpi,            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, imageReader.getSurface(), null, null);        try {            SystemClock.sleep(STOP_TIME);            Image image = imageReader.acquireLatestImage();            Image.Plane[] planes = image.getPlanes();            ByteBuffer buffer = planes[0].getBuffer();            int pixelStride = planes[0].getPixelStride();            int rowStride = planes[0].getRowStride();            int rowPadding = rowStride - pixelStride * width;            bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);            bitmap.copyPixelsFromBuffer(buffer);            image.close();        } catch (Exception e) {            e.printStackTrace();        } finally {            if (imageReader != null) {                imageReader.close();            }            if (projection != null) {                projection.stop();            }            if (display != null) {                display.release();            }        }        String outPath = "";        try {            outPath = saveImage(bitmap, context);        } catch (IOException e) {            e.printStackTrace();        }        return outPath;    }