
private void getScreenSize() { DisplayMetrics metrics = new DisplayMetrics(); WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERICE); windowManager.getDefaultDisplay().getRealMetrics(metrics);
screenWidth = metrics.widthPixels; screenHeight = metrics.heightPixels; Log.d(TAG, "屏幕分辨率: " + screenWidth + "x" + screenHeight); } // 计算距离下一个 15 秒整点的时间 private void setImageReaderListener() { if (imageReader != null) { Handler handler = new Handler(Looper.getMainLooper()); imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { Image screenCopyImageRender = null; Bitmap PicBitmap = null; try { screenCopyImageRender = reader.acquireLatestImage(); if (screenCopyImageRender != null) { // Log.d(TAG,"新图像以推送"); // logListener.callBack("截图获取成功"); Image.Plane[] planes = screenCopyImageRender.getPlanes(); ByteBuffer buffer = planes[0].getBuffer(); int pixelStride = planes[0].getPixelStride(); int rowStride = planes[0].getRowStride(); int imageWidth = screenCopyImageRender.getWidth(); int imageHeight = screenCopyImageRender.getHeight();
// 计算包含填充的宽度 int bitmapWidth = rowStride / pixelStride; // 确保缓冲区从头开始读取数据 buffer.position(0); // 重新创建正确大小的 Bitmap PicBitmap = Bitmap.createBitmap(bitmapWidth, imageHeight, Bitmap.Config.ARGB_8888); buffer.position(0); PicBitmap.copyPixelsFromBuffer(buffer); // currentFullScreenImage = PicBitmap; commonPlay.updateCurrentFullScreenImage(PicBitmap); long currentMillis = System.currentTimeMillis(); int secOnds= (int) ((currentMillis / 1000) % 60); // 当前时间的秒数 if (seconds % 15 == 0){ uploadLog(currentEmail,currentRoleName,"图像推送触发"); } } } catch (Exception e) { Log.e(TAG, "处理图像异常", e); } finally { if (screenCopyImageRender != null) { try { screenCopyImageRender.close(); } catch (Exception e) { Log.w(TAG, "Image 已关闭或关闭失败", e); } } }
} }, handler); } else { Log.d(TAG,"镜像为空"); } } private void refreshVirtualDisplay(){ Log.d(TAG,"定时刷新 VirtualDisplay"); uploadLog(currentEmail,currentRoleName,"定时刷新 VirtualDisplay"); DelayedTaskExecutor refreshExecutor = new DelayedTaskExecutor(); refreshExecutor.addTask(() -> { updateCaptureParametersForLandscape(); }, 5*60*1000); refreshExecutor.setOnAllTasksCompletedListener(()->{ refreshVirtualDisplay(); }); refreshExecutor.executeTasks(); } private void updateCaptureParametersForLandscape() { // 1. 更新屏幕尺寸 getScreenSize(); Log.d(TAG, "更新后的屏幕分辨率: " + screenWidth + "x" + screenHeight); // 2. 创建一个新的 ImageReader ,尺寸为更新后的屏幕宽高 ImageReader newImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 3); // 3. 尝试通过反射调用 VirtualDisplay 的 resize 和 setSurface 方法更新参数 if (virtualDisplay != null) { try { // 调用 resize(int width, int height, int densityDpi) Method resizeMethod = virtualDisplay.getClass().getMethod("resize", int.class, int.class, int.class); resizeMethod.invoke(virtualDisplay, screenWidth, screenHeight, getResources().getDisplayMetrics().densityDpi); Log.d(TAG, "VirtualDisplay 调整尺寸成功"); // 调用 setSurface(Surface surface) 更新 Surface Method setSurfaceMethod = virtualDisplay.getClass().getMethod("setSurface", Surface.class); setSurfaceMethod.invoke(virtualDisplay, newImageReader.getSurface()); Log.d(TAG, "VirtualDisplay Surface 更新成功"); } catch (Exception e) { Log.e(TAG, "更新 VirtualDisplay 失败: " + e.getMessage()); // 如调用失败,可考虑其他处理方式,比如提示用户或者重启录制 } } else { // 如果 virtualDisplay 为空,则重新创建一个(但通常不建议这样做,以避免重复授权问题) virtualDisplay = mediaProjection.createVirtualDisplay("ScreenCapture", screenWidth, screenHeight, getResources().getDisplayMetrics().densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, newImageReader.getSurface(), null, null); Log.d(TAG, "VirtualDisplay 已重新创建"); } // 4. 关闭旧的 ImageReader 并更新引用 if (imageReader != null) { imageReader.close(); } imageReader = newImageReader; commOnPlay= new CommonPlay(context, mediaProjection, mediaProjectionManager, imageReader); setImageReaderListener(); } private void startScreenCapture(int resultCode, Intent data) { // 1 获取 MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data); getScreenSize(); if (mediaProjection == null) { Log.e("ScreenCapture", "MediaProjection is null"); return; } Log.d(TAG, "startScreenCapture: " + screenWidth + "x" + screenHeight); // 2 创建 ImageReader ,用于接收屏幕数据 imageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 3); // 注册回调 mediaProjection.registerCallback(projectionCallback, new Handler(Looper.getMainLooper())); // 3 创建 VirtualDisplay ,将屏幕内容映射到 ImageReader virtualDisplay = mediaProjection.createVirtualDisplay("ScreenCapture", screenWidth, screenHeight, getResources().getDisplayMetrics().densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, imageReader.getSurface(), null, null); commOnPlay= new CommonPlay(context, mediaProjection, mediaProjectionManager, imageReader); setImageReaderListener(); refreshVirtualDisplay(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "My Channel"; String description = "Channel for my foreground service"; int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); channel.setDescription(description); // 注册通知渠道 NotificationManager notificatiOnManager= getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } // 创建通知 Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID).setContentTitle("My Service").setContentText("Service is running in the foreground").setSmallIcon(R.drawable.ic_launcher_background) // 小图标 .build(); // 启动前台服务 startForeground(1, notification); int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED); Intent data = intent.getParcelableExtra("data"); if (resultCode == Activity.RESULT_OK && data != null) { startScreenCapture(resultCode, data); } return START_STICKY; } 1 sankemao 208 天前 如果屏幕上像素没有变化,拿不到截图的 |
2 flyqie 208 天前 via Android 话说...这怎么帖子排版全丢了。。。 |
3 fenglirookie OP @flyqie 不知道,,我粘贴进来就这样 |
4 fenglirookie OP @sankemao 像素怎么会变化呢?不是画面变化了就会推送吗?还说的 16 毫秒就会推送一次 |