본문 바로가기
Flutter

Flutter에서 앱 스위처(App Switcher) 미리보기 화면 제어하기

by 안될개발 2025. 2. 19.

Flutter에서 앱 스위처(App Switcher) 미리보기 화면 제어하기

Flutter에서 앱 스위처(App Switcher) 미리보기 화면 제어하기

모바일 앱에서 사용자가 홈 버튼을 누르거나 앱 스위처(App Switcher) 화면으로 이동할 때 보안이 중요한 앱(예: 금융 앱, 비밀번호 관리 앱)에서는 현재 화면이 그대로 노출되지 않도록 보호할 필요가 있습니다.

Flutter에서는 iOS 및 Android 모두에서 앱 스위처 미리보기 화면을 변경하는 방법을 제공하며, 이 글에서는 각각의 구현 방법을 설명합니다.


1. iOS에서 앱 스위처 미리보기 화면 보호하기

iOS에서는 앱이 백그라운드로 전환될 때 UIApplication.didEnterBackgroundNotification 이벤트를 감지하여 보안 화면을 표시할 수 있습니다.

📌 iOS 설정 (AppDelegate.swift 수정)

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  var privacyView: UIView?

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    NotificationCenter.default.addObserver(
      self,
      selector: #selector(didEnterBackground),
      name: UIApplication.didEnterBackgroundNotification,
      object: nil
    )
    NotificationCenter.default.addObserver(
      self,
      selector: #selector(willEnterForeground),
      name: UIApplication.willEnterForegroundNotification,
      object: nil
    )
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  @objc func didEnterBackground() {
    let keyWindow = UIApplication.shared.windows.first
    privacyView = UIView(frame: keyWindow?.frame ?? CGRect.zero)
    privacyView?.backgroundColor = UIColor.systemGray6 // 블러 효과 대신 단색 배경
    keyWindow?.addSubview(privacyView!)
  }

  @objc func willEnterForeground() {
    privacyView?.removeFromSuperview()
  }
}

📌 코드 설명

  • 앱이 백그라운드로 진입하면 privacyView를 추가하여 기존 화면을 가립니다.
  • 사용자가 다시 앱으로 돌아오면 privacyView를 제거하여 원래 화면을 복원합니다.

✅ 참고: privacyView?.backgroundColor를 특정 이미지로 변경하면 금융 앱처럼 특정한 보안 화면을 띄울 수도 있습니다.


2. Android에서 앱 스위처 미리보기 화면 보호하기

Android에서는 FLAG_SECURE 플래그를 사용하여 앱이 백그라운드로 전환될 때 스크린샷을 방지할 수 있습니다.

📌 Android 설정 (MainActivity.kt 수정)

package com.example.app

import android.os.Bundle
import android.view.WindowManager
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.setFlags(
            WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE
        )
    }
}

📌 코드 설명

  • FLAG_SECURE 플래그를 활성화하면 앱 스위처에서 앱 화면이 보이지 않도록 보호할 수 있습니다.
  • 이 설정이 활성화되면 Android에서는 스크린샷 및 화면 녹화를 차단하게 됩니다.

✅ 주의: FLAG_SECURE가 활성화되면 사용자도 앱 내에서 스크린샷을 찍을 수 없습니다. 금융 앱 등 보안이 중요한 앱에서만 적용하는 것이 좋습니다.


3. Flutter에서 플랫폼 채널을 통해 제어하기

Flutter에서 직접 iOS와 Android의 기능을 제어하려면 **플랫폼 채널 (MethodChannel)**을 사용하여 FLAG_SECURE 또는 privacyView를 동적으로 활성화/비활성화할 수 있습니다.

📌 Flutter 코드 (Dart에서 네이티브 코드 호출)

import 'package:flutter/services.dart';

class PrivacyManager {
  static const MethodChannel _channel = MethodChannel('app_privacy');

  static Future<void> enablePrivacyMode() async {
    await _channel.invokeMethod('enablePrivacy');
  }

  static Future<void> disablePrivacyMode() async {
    await _channel.invokeMethod('disablePrivacy');
  }
}

📌 Android 네이티브 코드 수정 (MainActivity.kt)

import android.os.Bundle
import android.view.WindowManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "app_privacy"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "enablePrivacy" -> {
                    window.setFlags(
                        WindowManager.LayoutParams.FLAG_SECURE,
                        WindowManager.LayoutParams.FLAG_SECURE
                    )
                    result.success(null)
                }
                "disablePrivacy" -> {
                    window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
                    result.success(null)
                }
                else -> result.notImplemented()
            }
        }
    }
}

📌 iOS 네이티브 코드 수정 (AppDelegate.swift)

import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(name: "app_privacy", binaryMessenger: controller.binaryMessenger)

    channel.setMethodCallHandler { (call, result) in
      if call.method == "enablePrivacy" {
        self.addPrivacyScreen()
        result(nil)
      } else if call.method == "disablePrivacy" {
        self.removePrivacyScreen()
        result(nil)
      } else {
        result(FlutterMethodNotImplemented)
      }
    }
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  func addPrivacyScreen() {
    let privacyView = UIView(frame: UIScreen.main.bounds)
    privacyView.backgroundColor = UIColor.systemGray6
    window?.addSubview(privacyView)
  }

  func removePrivacyScreen() {
    window?.subviews.last?.removeFromSuperview()
  }
}

결론

Flutter에서 iOS와 Android의 앱 스위처 미리보기 화면을 보호하는 방법은 iOS에서는 UIView 추가, Android에서는 FLAG_SECURE 설정을 활용하는 것입니다.

  • 단순 적용: Android는 FLAG_SECURE, iOS는 privacyView를 추가하면 됩니다.
  • 동적 제어: 플랫폼 채널을 활용하여 Flutter에서 직접 보안 화면을 ON/OFF할 수 있습니다.

이 방법을 활용하면 보안이 필요한 앱에서도 보다 안전한 UX를 제공할 수 있습니다! 🚀