private void getScreenSize() { DisplayMetrics metrics = new DisplayMetrics(); WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 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;
}
|  |      1sankemao      154 天前 如果屏幕上像素没有变化,拿不到截图的 | 
|  |      2flyqie      154 天前 via Android 话说...这怎么帖子排版全丢了。。。 | 
|      3fenglirookie OP @flyqie 不知道,,我粘贴进来就这样 | 
|      4fenglirookie OP @sankemao 像素怎么会变化呢?不是画面变化了就会推送吗?还说的 16 毫秒就会推送一次 |