天天看點

android 兩種截屏方式

截屏的時候會有卡頓,暫時未解決。

第一種(這種截圖隻會截屏應用内,狀态欄是不會截到的):

調用方法

if (ContextCompat.checkSelfPermission(ShareCodeActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(ShareCodeActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 54);
                    Log.i("-->", "權限申請");
                } else {
                    screenshot();
                }
           

在調用之前需要判斷權限

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        doNext(requestCode, grantResults);
    }

    private void doNext(int requestCode, int[] grantResults) {

        if (requestCode == 54) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                screenshot();
            } else {

                new AlertDialog.Builder(this)
                        .setTitle("權限申請")
                        .setMessage("在設定-應用-(應用名稱)-權限中啟動存儲權限,以正常使用此功能")
                        .setPositiveButton("去設定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                                Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
                                startActivity(intent);
                            }
                        })
                        .setNegativeButton("取消", null)
                        .show();
            }
        }

    }
           

接下來是截圖的具體方法:

/**
     * 擷取螢幕
     */
    private void screenshot() {
        // 擷取螢幕
        View dView = getWindow().getDecorView();
        dView.setDrawingCacheEnabled(true);
        dView.buildDrawingCache();
        Bitmap bmp = dView.getDrawingCache();
        File file = PathGetUtils.getFile(this);
        if (bmp != null) {
            try {
                Log.i("-->", "路徑:" + file.getPath() + "  " + file.getAbsolutePath());
                if (file.exists()) {
                    file.delete();
                }
                FileOutputStream os = new FileOutputStream(file);
                bmp.compress(Bitmap.CompressFormat.PNG, 100, os);
                os.flush();
                os.close();
                String mUri = MediaStore.Images.Media.insertImage(getContentResolver(), file.getPath(), "ck", null);
                if (mUri != null) {
                    Toast.makeText(ShareCodeActivity.this, "截圖成功", Toast.LENGTH_SHORT).show();
                    // 最後通知圖庫更新
                    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    Uri uri = Uri.fromFile(new File(mUri));
                    intent.setData(uri);
                    sendBroadcast(intent);
                } else {
                    Toast.makeText(ShareCodeActivity.this, "截圖失敗", Toast.LENGTH_SHORT).show();
                }
            } catch (Exception e) {

            }
        }
    }
           

其中擷取的bitmap就是截屏圖檔.

第二種方法(這個隻支援5.0的系統以上,截取整個視圖):

調用方法,需要判斷api版本

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
                    mMpMngr = (MediaProjectionManager) getApplicationContext().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
                    if(NoDoubleClick.isFastClick()){
                        startIntent();
                    }
                }else {
                    Toast.makeText(this, "您的手機系統暫不支援截屏功能", Toast.LENGTH_SHORT).show();
                }
           

接下來是截圖的方法

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //3、通過onActivityResult()擷取授權結果。
        if (requestCode == REQUEST_MEDIA_PROJECTION && resultCode == RESULT_OK) {
            MyApp.mResultCode = resultCode;
            MyApp.mResultIntent = data;
            MyApp.mMpmngr = mMpMngr;
            newPrintScreen();
        }
    }

    private void startIntent() {
        if (MyApp.mResultIntent != null && MyApp.mResultCode != 0) {
            //已授權
            newPrintScreen();
        } else{
            //2、調用MediaProjectionManager.createScreenCaptureIntent()後,會彈出一個dialog詢問使用者是否授權應用捕捉螢幕
            startActivityForResult(mMpMngr.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);//未授權
        }

    }

    private void newPrintScreen(){
        wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metric = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(metric);
        windowWidth = metric.widthPixels;
        windowHeight = metric.heightPixels;
        screenDensity = metric.densityDpi;
        mImageReader = ImageReader.newInstance(windowWidth, windowHeight, 0x1, 2);
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG, "start startVirtual");
                startVirtual();
            }
        }, 000);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG, "start startCapture");
                startCapture();
            }
        }, 500);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG, "start stopVirtual");
                stopVirtual();
            }
        }, 1000);
    }

    private void stopVirtual() {
        if (mVirtualDisplay != null) {
            mVirtualDisplay.release();
            mVirtualDisplay = null;
        }
    }

    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 ");
                shareDialog(bitmap);
                if (mMpj != null) {
                    mMpj.stop();
                    mMpj = null;
                }
            } catch (IOException e) {
                Log.e(TAG, e.toString());
                e.printStackTrace();
            }
        }
    }

    private void startVirtual() {
        if (mMpj == null) mMpj = MyApp.mMpmngr.getMediaProjection(MyApp.mResultCode, MyApp.mResultIntent);
        mVirtualDisplay = mMpj.createVirtualDisplay("capture_screen", windowWidth, windowHeight, screenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);
    }
           

這種方法需要手動允許截屏的權限。