美文网首页
悬浮窗截取手机屏幕

悬浮窗截取手机屏幕

作者: 小玉1991 | 来源:发表于2019-12-06 19:46 被阅读0次

    用到了MediaProjection 和ImageReader,VirtualDisplay
    代码如下

    在Acticity中先申请权限

     public void requestCapturePermission() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                //5.0 之后才允许使用屏幕截图
                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) {
                        FloatWindowsService.setResultData(data);
                        startService(new Intent(getApplicationContext(), FloatWindowsService.class));
                    }
                    break;
            }
    
        }
    

    悬浮窗继承并注册Sercvice,系统API截图的代码

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public class FloatWindowsService extends Service {
        private long mCounts;
        public static Intent newIntent(Context context, Intent mResultData) {
            Intent intent = new Intent(context, FloatWindowsService.class);
            if (mResultData != null) {
                intent.putExtras(mResultData);
            }
            return intent;
        }
    
        private MediaProjection mMediaProjection;
        private VirtualDisplay mVirtualDisplay;
    
        private static Intent mResultData = null;
    
    
        private ImageReader mImageReader;
        private WindowManager mWindowManager;
        private WindowManager.LayoutParams mLayoutParams;
        private GestureDetector mGestureDetector;
    
        private ImageView mFloatView;
        private int mScreenWidth;
        private int mScreenHeight;
        private int mScreenDensity;
        private static final String PATH = APP_DIR + "ScreenCapture/";
        @Override
        public void onCreate() {
            super.onCreate();
            createFloatView();
        }
        public static Intent getResultData() {
            return mResultData;
        }
        public static void setResultData(Intent mResultData) {
            FloatWindowsService.mResultData = mResultData;
        }
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        @SuppressLint("ClickableViewAccessibility")
        private void createFloatView() {
            mGestureDetector = new GestureDetector(getApplicationContext(), new FloatGestrueTouchListener());
            mLayoutParams = new WindowManager.LayoutParams();
            mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics metrics = new DisplayMetrics();
            mWindowManager.getDefaultDisplay().getMetrics(metrics);
            mScreenDensity = metrics.densityDpi;
            mScreenWidth = metrics.widthPixels;
            mScreenHeight = metrics.heightPixels;
    
            mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
            mLayoutParams.format = PixelFormat.RGBA_8888;
            // 设置Window flag
            mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
            mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
            mLayoutParams.x = mScreenWidth;
            mLayoutParams.y = 100;
            mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
            mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
    
    
            mFloatView = new ImageView(getApplicationContext());
            mFloatView.setImageBitmap(BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_compass));
            mWindowManager.addView(mFloatView, mLayoutParams);
    
            mFloatView.setOnTouchListener((v, event) -> mGestureDetector.onTouchEvent(event));
        }
    
    
        private class FloatGestrueTouchListener implements GestureDetector.OnGestureListener {
            int lastX, lastY;
            int paramX, paramY;
    
            @Override
            public boolean onDown(MotionEvent event) {
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                paramX = mLayoutParams.x;
                paramY = mLayoutParams.y;
                return true;
            }
    
            @Override
            public void onShowPress(MotionEvent e) {
    
            }
    
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                startScreenShot();
                return true;
            }
    
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                int dx = (int) e2.getRawX() - lastX;
                int dy = (int) e2.getRawY() - lastY;
                mLayoutParams.x = paramX + dx;
                mLayoutParams.y = paramY + dy;
                // 更新悬浮窗位置
                mWindowManager.updateViewLayout(mFloatView, mLayoutParams);
                return true;
            }
    
            @Override
            public void onLongPress(MotionEvent e) {
    
            }
    
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                return false;
            }
        }
    
    
        private void startScreenShot() {
            Logger.info("FloatWin", "start-->" + System.currentTimeMillis());
            mFloatView.setVisibility(View.GONE);
            if (mMediaProjection != null) {
                virtualDisplay();
            } else {
                setUpMediaProjection();
                virtualDisplay();
            }
        }
    
    
        public void setUpMediaProjection() {
            if (mResultData == null) {
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.addCategory(Intent.CATEGORY_LAUNCHER);
                startActivity(intent);
            } else {
                mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
            }
        }
    
        private MediaProjectionManager getMediaProjectionManager() {
    
            return (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        }
    
        private void virtualDisplay() {
    
            // createImageReader
            mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1);
    
            mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
                    mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                    mImageReader.getSurface(), null, null);
    
            mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
    
                    Image image = reader.acquireLatestImage();
    
                    Logger.info("FloatWin", "get image-->" + System.currentTimeMillis());
                    Bitmap bitmap = null;
                    try {
                        if (image != null) {
                            bitmap = saveBitmap(image);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (image != null) {
                            image.close();
                        }
                        SaveTask mSaveTask = new SaveTask();
                        mSaveTask.execute(bitmap);
    
                        mImageReader.close();
                    }
    
    
                }
            }, getBackgroundHandler());
        }
    
    
        Handler backgroundHandler;
    
        private Handler getBackgroundHandler() {
            if (backgroundHandler == null) {
                HandlerThread backgroundThread =
                        new HandlerThread("catwindow", android.os.Process
                                .THREAD_PRIORITY_BACKGROUND);
                backgroundThread.start();
                backgroundHandler = new Handler(backgroundThread.getLooper());
            }
            return backgroundHandler;
        }
    
        public class SaveTask extends AsyncTask<Bitmap, Void, Bitmap> {
    
            @Override
            protected Bitmap doInBackground(Bitmap... params) {
                if (params == null || params.length < 1 || params[0] == null) {
                    return null;
                }
                Bitmap bitmap = params[0];
                return bitmap;
            }
    
            @Override
            protected void onPostExecute(Bitmap bitmap) {
                super.onPostExecute(bitmap);
                //主线程中提示
                if (bitmap != null) {
                    mCounts = 0;
                    Logger.info("FloatWin", "saved image-->" + System.currentTimeMillis());
                    bitmap.recycle();
                    CustomToast.showGrayToast(getApplicationContext(), "保存成功");
                    mFloatView.setVisibility(View.VISIBLE);
                } else {
                    mCounts++;
    
                    if (mCounts < 10) {
                        Logger.info("FloatWin", "image is null, reshot");
                        startScreenShot();
                    }else {
                        Logger.info("FloatWin", "image is null, retry too many times");
                    }
    
                }
    
    
            }
        }
    
        @Nullable
        private Bitmap saveBitmap(Image image) {
            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);
    
            File fileImage = null;
            if (bitmap != null) {
                try {
                    File forder = new File(PATH);
                    if (!forder.exists()) {
                        forder.mkdir();
                    }
    
                    fileImage = new File(PATH + System.currentTimeMillis() + ".jpg");
                    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;
        }
    
    
        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() {
            // to remove mFloatLayout from windowManager
            super.onDestroy();
            if (mFloatView != null) {
                mWindowManager.removeView(mFloatView);
            }
            stopVirtual();
            tearDownMediaProjection();
        }
    
    }
    

    相关文章

      网友评论

          本文标题:悬浮窗截取手机屏幕

          本文链接:https://www.haomeiwen.com/subject/uboegctx.html