sdk 截屏之调用系统截屏

前天写了一篇截图(截屏)–未调用系统截屏管理,今天介绍一篇关于利用系统截屏的

其一:申请的权限如下:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

其二:关于TargetSdkVersion的版本 大小–最好选择在23以下(给用户去选择申请权限)

其三:其思想和上一篇文章是一样的 ,这里就不介绍了,直接贴代码
主体部分:

private ImageView mImageCupView;
    private MediaProjectionManager mMediaProjectionManager;
    private int mScreenWidth;
    private int mScreenHeight;
    private int mScreenDensity;
    private ImageReader mImageReader;
    private MediaProjection mMediaProjection;
    private VirtualDisplay mVirtualDisplay;
    public static final int REQUEST_MEDIA_PROJECTION = 18;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取当前屏幕的像素点
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        mScreenDensity = metrics.densityDpi;
        mScreenWidth = metrics.widthPixels;
        mScreenHeight = metrics.heightPixels;
        //5 表示接受的权限的最多次数(拒绝5次就会崩溃)
        mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 5);
        //检查其版本号
        requestCapturePermission();
        mImageCupView = (ImageView) findViewById(R.id.cupView);
        findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mMediaProjection == null) {
                    //判断是否获取到权限,否则开启重新开启权限
                    Toast.makeText(MainActivity.this,"您必须接受开启权限",Toast.LENGTH_SHORT).show();
                    requestCapturePermission();
                }
                startScreenShot();
            }
        });
    }

    private void startScreenShot() {
        Handler handler1 = new Handler();
        handler1.postDelayed(new Runnable() {
            public void run() {
                //start virtual
                virtualDisplay();
            }
        }, 5);

        handler1.postDelayed(new Runnable() {
            public void run() {
                //capture the screen
                startCapture();
            }
        }, 30);
    }

    private void startCapture() {

        Image image = mImageReader.acquireLatestImage();
        if (image == null) {
            //开始截屏
            startScreenShot();
        } else {
            //保存截屏
            SaveTask mSaveTask = new SaveTask();
            AsyncTaskCompat.executeParallel(mSaveTask, image);

        }
    }

    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();
            File fileImage = null;
            if (bitmap != null) {
                try {
                    fileImage = new File(FileUtil.getScreenShotsName(getApplicationContext()));
                    if (!fileImage.exists()) {
                        fileImage.createNewFile();
                    }
                    FileOutputStream out = new FileOutputStream(fileImage);
                    if (out != null) {
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

                        out.flush();
                        out.close();
                        //发送广播给相册--更新相册图片
                        Intent media = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                        Uri contentUri = Uri.fromFile(fileImage);
                        media.setData(contentUri);
                        sendBroadcast(media);

                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    fileImage = null;
                } catch (IOException e) {
                    e.printStackTrace();
                    fileImage = null;
                }
            }

            if (fileImage != null) {
                return bitmap;
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //预览图片
            if (bitmap != null) {
                Toast.makeText(MainActivity.this,"截图已经成功保存到相册",Toast.LENGTH_SHORT).show();
                //直接设置动画效果
                setAnimation(bitmap);

            }
        }
    }

    private void setAnimation(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        ViewGroup.LayoutParams layoutParams = mImageCupView.getLayoutParams();
        layoutParams.height = height;
        layoutParams.width = width;
        //mImagerCupView是布局文件中创建的
        mImageCupView.setLayoutParams(layoutParams);
        mImageCupView.setImageBitmap(bitmap);
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator animatory = ObjectAnimator.ofFloat(mImageCupView, "scaleY", 1.0f, 0.0f);
        ObjectAnimator animatorx = ObjectAnimator.ofFloat(mImageCupView, "scaleX", 1.0f, 0.0f);
        animatorSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //后面可以继续接着写其他活动,如页面的跳转等等

            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animatorSet.setDuration(500);
        animatorSet.play(animatory).with(animatorx);//两个动画同时开始
        animatorSet.start();
    }

    private void virtualDisplay() {
        if(mMediaProjection != null) {
            mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
                    mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                    mImageReader.getSurface(), null, null);
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void requestCapturePermission() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            Toast.makeText(this, "不能截屏", Toast.LENGTH_LONG).show();
            return;
        }
        //获取截屏的管理器
        mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        startActivityForResult(mMediaProjectionManager.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) {
                    mMediaProjection = mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, data);
                }
                break;
        }
    }

    private void tearDownMediaProjection() {
        if (mMediaProjection != null) {
            mMediaProjection.stop();
            mMediaProjection = null;
        }
    }

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

    // 结束后销毁
    @Override
    public void onDestroy() {
        super.onDestroy();
        stopVirtual();
        tearDownMediaProjection();
    }

工具类:如下

public class FileUtil {

    //系统保存截图的路径
    public static final String SCREENCAPTURE_PATH = "ScreenCapture" + File.separator + "Screenshots" + File.separator;
    public static final String SCREENSHOT_NAME = "Screenshot";

    public static String getAppPath(Context context) {

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            return Environment.getExternalStorageDirectory().toString();
        } else {
            return context.getFilesDir().toString();
        }
    }


    public static String getScreenShots(Context context) {

        StringBuffer stringBuffer = new StringBuffer(getAppPath(context));
        stringBuffer.append(File.separator);

        stringBuffer.append(SCREENCAPTURE_PATH);

        File file = new File(stringBuffer.toString());

        if (!file.exists()) {
            file.mkdirs();
        }
        return stringBuffer.toString();
    }

    public static String getScreenShotsName(Context context) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");

        String date = simpleDateFormat.format(new Date());

        StringBuffer stringBuffer = new StringBuffer(getScreenShots(context));
        stringBuffer.append(SCREENSHOT_NAME);
        stringBuffer.append("_");
        stringBuffer.append(date);
        stringBuffer.append(".png");
        return stringBuffer.toString();
    }
}

以上,就不做解释了

以下是使用Windows SDK和DirectX SDK来构建dxgi截屏的步骤: 1. 安装Windows SDK和DirectX SDK 2. 创建工程,并将以下头文件包含进来: ``` #include <d3d11.h> #include <dxgi1_2.h> #include <iostream> #include <fstream> #include <vector> #include <string> ``` 3. 创建一个D3D11设备和设备上下文: ``` D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &m_pd3dDevice, NULL, &m_pd3dDeviceContext); ``` 4. 获取DXGI设备: ``` IDXGIDevice* pDXGIDevice; m_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice); ``` 5. 获取DXGI适配器: ``` IDXGIAdapter* pDXGIAdapter; pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&pDXGIAdapter); ``` 6. 获取DXGI工厂: ``` IDXGIFactory* pIDXGIFactory; pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&pIDXGIFactory); ``` 7. 枚举所有显示器: ``` std::vector<IDXGIOutput*> arrOutputs; IDXGIOutput* pOutput; for (int i = 0; pIDXGIFactory->EnumOutputs(i, &pOutput) != DXGI_ERROR_NOT_FOUND; ++i) { arrOutputs.push_back(pOutput); } ``` 8. 获取输出的描述: ``` DXGI_OUTPUT_DESC outputDesc; arrOutputs[0]->GetDesc(&outputDesc); ``` 9. 获取DXGI输出: ``` IDXGIOutput1* pDXGIOutput1; arrOutputs[0]->QueryInterface(__uuidof(IDXGIOutput1), (void**)&pDXGIOutput1); ``` 10. 获取桌面信息: ``` DXGI_OUTDUPL_DESC outputDuplDesc; pDXGIOutput1->DuplicateOutput(m_pd3dDevice, &outputDuplDesc); ``` 11. 创建DXGI资源: ``` ID3D11Texture2D* pTexture; D3D11_TEXTURE2D_DESC desc; desc.Width = outputDuplDesc.ModeDesc.Width; desc.Height = outputDuplDesc.ModeDesc.Height; desc.Format = outputDuplDesc.ModeDesc.Format; desc.ArraySize = 1; desc.BindFlags = D3D11_BIND_FLAG::D3D11_BIND_RENDER_TARGET; desc.Usage = D3D11_USAGE::D3D11_USAGE_DEFAULT; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.MipLevels = 1; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; m_pd3dDevice->CreateTexture2D(&desc, NULL, &pTexture); ``` 12. 创建渲染目标视图: ``` ID3D11RenderTargetView* pRenderTargetView; m_pd3dDevice->CreateRenderTargetView(pTexture, NULL, &pRenderTargetView); ``` 13. 设置渲染目标: ``` m_pd3dDeviceContext->OMSetRenderTargets(1, &pRenderTargetView, NULL); ``` 14. 渲染: ``` m_pd3dDeviceContext->ClearRenderTargetView(pRenderTargetView, DirectX::Colors::Black); m_pd3dDeviceContext->Draw(3, 0); ``` 15. 保存截屏: ``` D3D11_TEXTURE2D_DESC desc; pTexture->GetDesc(&desc); D3D11_MAPPED_SUBRESOURCE mappedResource; m_pd3dDeviceContext->Map(pTexture, 0, D3D11_MAP_READ, 0, &mappedResource); std::ofstream ofs("screenshot.bmp", std::ios::binary); const uint8_t* src = (const uint8_t*)mappedResource.pData; for (int y = 0; y < desc.Height; ++y) { const uint8_t* row = src + mappedResource.RowPitch * y; for (int x = 0; x < desc.Width; ++x) { const uint8_t* pixel = row + x * 4; ofs.put(pixel[2]); ofs.put(pixel[1]); ofs.put(pixel[0]); } } m_pd3dDeviceContext->Unmap(pTexture, 0); ofs.close(); ``` 以上就是使用Windows SDK和DirectX SDK来构建dxgi截屏的步骤。需要注意的是,如果您正在使用Windows 10或更高版本,则可以使用Windows.Graphics.Capture命名空间来实现更简单的截屏
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值