android mediaProjection 截屏 旋转屏幕之后如何保持权限?

72 阅读2分钟

如题 我按照如下代码编写之后 在旋转屏幕时 报错 说 权限失效需要重新获取权限,有办法保持之前的权限吗?不然每次旋转屏幕都要获取权限 那好傻啊 ` public class FightFloatOperaPanelService extends Service { private static final String TAG = "NotesPanelService"; private Context context; private WindowManager windowManager; private MediaProjection mediaProjection; private boolean mediaProjectionCallbackRegistered = false; private MediaProjectionManager mediaProjectionManager; private ImageReader imageReader; private VirtualDisplay virtualDisplay; private int screenWidth; private int screenHeight;

MediaProjection.Callback projectionCallback = new MediaProjection.Callback() {
    @Override
    public void onStop() {
        super.onStop();
        releaseResources();

        // 在这里清理虚拟显示器、释放资源等
    }
};
// 用于监听配置变化的广播接收器
private final BroadcastReceiver configurationChangeReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
            // 获取当前屏幕方向
            int orientation = getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                // 横屏时更新捕获参数
                updateCaptureParametersForLandscape(false);
                Log.d(TAG, "已更新为横屏参数");
            } else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                updateCaptureParametersForLandscape(false);
                // 若需要,也可在竖屏时做相应处理
                Log.d(TAG, "当前为竖屏");
            }
        }
    }
};
 public void onCreate() {
    super.onCreate();
    IntentFilter filter = new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
    registerReceiver(configurationChangeReceiver, filter);
     windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    context = this;
 }
 
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);
}

private void setScreenImageUpdateListener(){
    if (mediaProjection == null) {
        Log.d(TAG,"请先获取截屏权限");
    } else {
        Log.d(TAG,"开始截屏");
        // 获取最新截图
        // 使用回调监听新图像
        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);

                            screenCopyImageRender.close();

// long currentTimeMillis = System.currentTimeMillis(); // int seconds = (int) ((currentTimeMillis / 1000) % 60); //// 每个45秒发送一次心跳 // if(seconds == 45){ // sendImagePushHeartbeat(); // } } } catch (Exception e) { if (screenCopyImageRender != null) { screenCopyImageRender.close(); } } finally { if (screenCopyImageRender != null) { screenCopyImageRender.close(); } }

                }
            }, handler);
        } else {
            Log.d(TAG,"镜像为空");
        }
    }
}

private void updateCaptureParametersForLandscape(Boolean isInit){
    if(isInit){
        initCaptureParametersForLandscapeExecutor();
    }else{
        updateCaptureParametersForLandscapeExecutor();
    }

}
private void initCaptureParametersForLandscapeExecutor() {
    // 1. 更新屏幕尺寸


    getScreenSize();
    Log.d(TAG, "更新后的屏幕分辨率: " + screenWidth + "x" + screenHeight);
    // 1. 释放旧资源
    releaseResources();


    // 2. 新建 ImageReader
    imageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);
    Surface surface = imageReader.getSurface();

    // 3. 创建 VirtualDisplay
    virtualDisplay = mediaProjection.createVirtualDisplay(
            "ScreenCapture",
            screenWidth,
            screenHeight,
            context.getResources().getDisplayMetrics().densityDpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            surface,
            null,
            null
    );
    Log.d(TAG, "更新后的屏幕分辨率: 后即将开始监听");
    setScreenImageUpdateListener();
}
private void releaseResources() {
    if (virtualDisplay != null) {
        virtualDisplay.release();
        virtualDisplay = null;
    }
    if (imageReader != null) {
        imageReader.close();
        imageReader = null;
    }
}
private void updateCaptureParametersForLandscapeExecutor() {
    // 1. 更新屏幕尺寸
    getScreenSize();
    Log.d(TAG, "updateCaptureParametersForLandscapeExecutor 更新后的屏幕分辨率: " + screenWidth + "x" + screenHeight);

    // 2. 释放旧资源,但不要释放 mediaProjection
    releaseResources();

    // 3. 创建新的 ImageReader
    imageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);
    Surface surface = imageReader.getSurface();
    // 5. 创建 VirtualDisplay
    virtualDisplay = mediaProjection.createVirtualDisplay(
            "ScreenCapture",
            screenWidth,
            screenHeight,
            context.getResources().getDisplayMetrics().densityDpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            surface,
            null,
            null
    );
    Log.d(TAG, "更新完成,开始设置图像监听器");
    setScreenImageUpdateListener();
}

@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();
    Log.d(TAG,"初始化进入");
    // 启动前台服务
    startForeground(1, notification);
    int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
    Intent data = intent.getParcelableExtra("data");
    if (resultCode == Activity.RESULT_OK && data != null) {
        mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
        // 1️⃣ 获取 MediaProjection
        if (!mediaProjectionCallbackRegistered) {
            mediaProjection.registerCallback(projectionCallback, new Handler(Looper.getMainLooper()));
            mediaProjectionCallbackRegistered = true;
        }
        getScreenSize();
        Log.d(TAG, "startScreenCapture: " + screenWidth + "x" + screenHeight);
        // 注册回调

        // 2️⃣ 创建 ImageReader,用于接收屏幕数据
        Log.d(TAG, "初始化 开始V");
        updateCaptureParametersForLandscape(true);
    }
    return START_STICKY;
}

}`