美文网首页Android开发经验谈Android开发安卓开发
Android5.0以上截图方法,适配targetSdkVers

Android5.0以上截图方法,适配targetSdkVers

作者: 猪八戒表哥 | 来源:发表于2021-05-14 22:35 被阅读0次

    适配了Android5.0以上的截图方法,实现了后台连续截图;使用该方法请求授权同意后开始截图:

    private MediaProjectionManager mMediaProjectionManager;
      public void getMediaProjectionManger() {
            mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
            if (mMediaProjectionManager != null) {
                startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), RECORD_REQUEST_CODE);
            }
        }
    

    由于targetSdkVersion 29及以上要求getMediaProjection需要再前台服务执行,所以在onActivityResult里面启动服务:

     @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
                Intent intent = new Intent(ZkScreenshotActivity.this, ZkA5AboveScreenshotService.class);
                intent.putExtra("code",resultCode);
                intent.putExtra("data",data);
                ZkUtlis.startService(ZkScreenshotActivity.this,intent);
            }
        }
    

    Service方法如下:

     public class ZkA5AboveScreenshotService extends Service {
    
        private String mTag = "ZkA5AboveScreenshotService";
    
        private int mResultCode;
    
        private Intent mResultData;
    
        private MediaProjection mMediaProjection;
    
        private MediaProjectionManager mMediaProjectionManager;
    
        private int mWidth;
    
        private int mHeight;
    
        private int mDensity;
    
        private ImageReader mImageReader;
    
        private int mImagesProduced;
    
        private int mCount = 0;
    
        @Override
        public void onCreate() {
            super.onCreate();
            mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            createNotificationChannel();
            mResultCode = intent.getIntExtra("code", -1);
            mResultData = intent.getParcelableExtra("data");
            mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, Objects.requireNonNull(mResultData));
            Log.d(mTag, "mMediaProjection created: " + mMediaProjection);
            startCaptureReader();
            return super.onStartCommand(intent, flags, startId);
        }
    
        /**
         * startCaptureReader
         */
        @SuppressLint("WrongConstant")
        private void startCaptureReader() {
            WindowManager wm = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);
            Display display = wm.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            mWidth = size.x;
            mHeight = size.y;
            Log.d(mTag,"width:" + mWidth + "   height:" + mHeight);
            DisplayMetrics metrics = getResources().getDisplayMetrics();
            mDensity = metrics.densityDpi;
            // start capture reader
            mImageReader = ImageReader.newInstance(mWidth, mHeight, 0x01, 2);
            mMediaProjection.createVirtualDisplay("screencap", mWidth, mHeight, mDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);
            mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), null);
        }
    
        /**
         * ImageAvailableListener
         */
        private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
            @Override
            public void onImageAvailable(ImageReader reader) {
                try (Image image = reader.acquireLatestImage()) {
                    if (image != null) {
                          /**
                           * 截图结果,会在内容更新自动回调,该方法可以实现连续截图,无需重复启用截图方法
                           */
    
                        }
                        image.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * Create Notification Channel
         */
        private void createNotificationChannel() {
            //获取一个Notification构造器
            Notification.Builder builder = new Notification.Builder(this.getApplicationContext());
            //点击后跳转的界面,可以设置跳转数据
            Intent nfIntent = new Intent(this, ZkScreenshotActivity.class);
            // 设置PendingIntent
            builder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0))
                    // 设置下拉列表中的图标(大图标)
                    .setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_launcher))
                    // 设置下拉列表里的标题
                    //.setContentTitle("SMI InstantView")
                    // 设置状态栏内的小图标
                    .setSmallIcon(R.mipmap.ic_launcher)
                    // 设置上下文内容
                    .setContentText("is running......")
                    // 设置该通知发生的时间
                    .setWhen(System.currentTimeMillis());
    
            /*以下是对Android 8.0的适配*/
            //普通notification适配
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                builder.setChannelId("notification_id");
            }
            //前台服务notification适配
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
                NotificationChannel channel = new NotificationChannel("notification_id", "notification_name", NotificationManager.IMPORTANCE_LOW);
                notificationManager.createNotificationChannel(channel);
            }
            // 获取构建好的Notification
            Notification notification = builder.build();
            //设置为默认的声音
            notification.defaults = Notification.DEFAULT_SOUND;
            startForeground(110, notification);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(mTag, "Service onDestroy");
            if (mImageReader != null) {
                mImageReader.setOnImageAvailableListener(null,null);
                mImageReader.close();
                mImageReader = null;
            }
            if (mMediaProjection != null) {
                mMediaProjection.stop();
                mMediaProjection = null;
            }
            mMediaProjectionManager = null;
        }
    

    下面是将Image转Bitmap

     /**
         * Image 转 Bitmap
         * @param image
         */
        private Bitmap imageToBitmap(Image image) {
            Image.Plane[] planes = image.getPlanes();
            ByteBuffer buffer = planes[0].getBuffer();
            int pixelStride = planes[0].getPixelStride();
            int rowStride = planes[0].getRowStride();
            int rowPadding = rowStride - pixelStride * mWidth;
    
            Bitmap bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
            bitmap.copyPixelsFromBuffer(buffer);
            return bitmap; 
        }
    

    相关文章

      网友评论

        本文标题:Android5.0以上截图方法,适配targetSdkVers

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