투케이2K

239. (ios/swift) AVPlayerViewController 동영상 재생 시 PIP 모드 설정 및 화면 전환 실시 본문

IOS

239. (ios/swift) AVPlayerViewController 동영상 재생 시 PIP 모드 설정 및 화면 전환 실시

투케이2K 2022. 11. 3. 21:12

[개발 환경 설정]

개발 툴 : XCODE

개발 언어 : SWIFT

 

[사전 설정]

 

[AppDelegate : 소스 코드]

import UIKit
import AVFoundation

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    
    // MARK: - [클래스 설명]
    /*
    // -----------------------------------------
    1. 애플리케이션 딜리게이트
    // -----------------------------------------
    */
    
    
    
    
    
    // MARK: - [빠른 로직 찾기 : 주석 로직 찾기]
    // -----------------------------------------
    // [SEARCH FAST] : [프리퍼런스 값 초기화 실시]
    // [SEARCH FAST] : [푸시 알림 뱃지 카운트 초기화]
    // [SEARCH FAST] : [빌드 타입 확인 실시]
    // -----------------------------------------
    
    
    
    
    
    // MARK: - [전역 변수 선언 실시]
    var window: UIWindow? // [ios 13 미만 버전 제어 위해 선언]



    
    
    // MARK: - [앱 프로세스 완료 및 앱 실행 실시]
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        print("")
        print("====================================")
        print("[AppDelegate >> didFinishLaunchingWithOptions]")
        print("-------------------------------")
        print("설 명 :: 앱 프로세스 완료 및 앱 실행 실시")
        print("====================================")
        print("")
        
        
        // -----------------------------------------
        // [애플리케이션 화면 잠김 및 꺼짐 상태 방지 / true = 꺼짐 방지]
        UIApplication.shared.isIdleTimerDisabled = true
        // -----------------------------------------
        
        
        // -----------------------------------------
        // MARK: - [PIP 모드를 실행하기 위한 버튼 추가 실시]
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(.playback)
            
            print("")
            print("====================================")
            print("[AppDelegate >> didFinishLaunchingWithOptions]")
            print("-------------------------------")
            print("설 명 :: ", "PiP 버튼 생성 실시")
            print("====================================")
            print("")
        } catch {
            print("")
            print("====================================")
            print("[AppDelegate >> didFinishLaunchingWithOptions]")
            print("-------------------------------")
            print("error :: ", "PiP 버튼 생성 에러")
            print("====================================")
            print("")
        }
        // -----------------------------------------

        
        // -----------------------------------------
        return true
        // -----------------------------------------
    }



    
    
    // MARK: - [Scene 만들기 위한 구성 객체 반환 : 스토리보드 , info]
    @available(iOS 13.0, *)
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        print("")
        print("====================================")
        print("[AppDelegate >> configurationForConnecting]")
        print("-------------------------------")
        print("설 명 :: Scene 만들기 위한 구성 객체 반환 : 스토리보드 , info")
        print("====================================")
        print("")

        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    
    
    
    
    // MARK: - [Scene 구성 객체 해제 실시]
    @available(iOS 13.0, *)
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        print("")
        print("====================================")
        print("[AppDelegate >> didDiscardSceneSessions]")
        print("-------------------------------")
        print("설 명 :: Scene 구성 객체 해제 실시")
        print("====================================")
        print("")
    }
    
    
    
    
    
    // MARK: - [애플리케이션 사용자가 작업 태스크 날린 이벤트 감지]
    func applicationWillTerminate(_ application: UIApplication) {
        print("")
        print("====================================")
        print("[AppDelegate >> applicationWillTerminate]")
        print("-------------------------------")
        print("설 명 :: 애플리케이션 사용자가 작업 태스크 날린 이벤트 감지")
        print("====================================")
        print("")
    }
    
    
    
    
    
    // MARK: - [디바이스 화면 세로 모드 고정 실시]
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        /*
        print("")
        print("====================================")
        print("[AppDelegate >> supportedInterfaceOrientationsFor]")
        print("-------------------------------")
        print("설 명 :: 디바이스 화면 세로 모드 고정 실시")
        print("====================================")
        print("")
        // */
        
        // [세로 방향 고정]
        return UIInterfaceOrientationMask.portrait
    }
    

} // [클래스 종료]
 

[ViewController : 소스 코드]

import UIKit
import Foundation
import AVKit
import AVFoundation

class A_Intro: UIViewController, AVPlayerViewControllerDelegate {
    
    
    // MARK: - [전역 변수 선언 실시]
    let ACTIVITY_NAME = "A_Intro"
    
    
    
    
    
    // MARK: - [뷰 로드 실시]
    override func viewDidLoad() {
        super.viewDidLoad()
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 뷰 로드 실시]")
        print("====================================")
        print("")
        
        // [테스트 함수 실행 실시]
        self.testMain()
    }
    
    
    
    
    
    // MARK: - [뷰 로드 완료]
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> viewWillAppear() :: 뷰 로드 완료]")
        print("====================================")
        print("")
    }
        
    
    
    
    
    // MARK: - [뷰 화면 표시]
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> viewDidAppear() :: 뷰 화면 표시]")
        print("====================================")
        print("")
        
    }
        
    
    
    
    
    // MARK: - [뷰 정지 상태]
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> viewWillDisappear() :: 뷰 정지 상태]")
        print("====================================")
        print("")
    }
        
    
    
    
    
    // MARK: - [뷰 종료 상태]
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> viewDidDisappear() :: 뷰 종료 상태]")
        print("====================================")
        print("")
    }
    
    
    
    
    
    
    // MARK: - [테스트 메인 함수 정의 실시]
    func testMain() {
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> testMain() :: 테스트 함수 시작 실시]")
        print("====================================")
        print("")
        
        
        /*
         // -----------------------------
         [요약 설명]
         // -----------------------------
         1. AVPlayer : 비디오 재생을 수행할 수 있습니다
         // -----------------------------
         2. 필요 info plist 설정 :
         
         [https 통신 사용] App Transport Security Settings >> Allow Arbitrary Loads >> YES
         // -----------------------------
         3. 필요 import 설정 :
         
         import AVKit
         import AVFoundation
         // -----------------------------
         */
        
        
        // [비동기 처리 수행]
        DispatchQueue.main.async {
            
            // [1]. 비디오 재생을 수행하기 위한 URL 지정
            let urlData = URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
            
            
            // [2]. 비디오 재생을 위한 AVPlayer() 선언 실시
            let avPlayer = AVPlayer(url: urlData!)
            
            
            // [3]. 비디오 재생 제어를 위한 AVPlayerViewController 선언 실시
            let avController = AVPlayerViewController()
            
            
            // [4]. 컨트롤러에 AVPlayer 지정 실시
            avController.player = avPlayer
            
            
            // [5]. 화면 사이즈 지정 실시 (전체 화면)
            avController.view.frame = self.view.frame
            
            
            // [6]. PIP 모드를 지원하는 경우 PIP 모드 설정 추가
            if AVPictureInPictureController.isPictureInPictureSupported() {
                print("")
                print("====================================")
                print("[\(self.ACTIVITY_NAME) >> testMain() :: PiP 모드 지원 함]")
                print("====================================")
                print("")
                
                avController.allowsPictureInPicturePlayback = true
            }
            else {
                print("")
                print("====================================")
                print("[\(self.ACTIVITY_NAME) >> testMain() :: PiP 모드 지원 안함]")
                print("====================================")
                print("")
            }
            
            
            // [7]. 딜리게이트 지정 실시
            avController.delegate = self
            
            
            // [8]. 동영상 재생 완료 상태 감지 등록
            NotificationCenter.default.addObserver(self, selector: #selector(self.didfinishPlaying(note:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: avPlayer.currentItem)
            
            
            // [9]. 동영상 재생 실시
            self.present(avController, animated: true, completion: nil)
            avPlayer.play()
        }

    }
    
    
    
    
    
    // MARK: - [동영상 >> PIP 모드 전환 실시]
    func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(_ playerViewController: AVPlayerViewController) -> Bool {
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> playerViewController() :: PIP 모드 동영상 전환 실시]")
        print("====================================")
        print("")
        
        return false
    }
    
    
    
    
    
    // MARK: - [PIP 모드에서 다시 전체 화면 전환 이벤트 감지]
    func playerViewController(_ playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> playerViewController() :: PIP 모드에서 다시 화면 복귀 수행 [2]]")
        print("====================================")
        print("")
        
        let currentviewController = navigationController?.visibleViewController
        
        if currentviewController != playerViewController{
            
            currentviewController?.present(playerViewController, animated: true, completion: nil)
            
        }
        
    }
    
    
    
    
    // MARK: - [동영상 재생 완료 이벤트 감지]
    @objc func didfinishPlaying(note : NSNotification)  {
        print("")
        print("====================================")
        print("[\(self.ACTIVITY_NAME) >> didfinishPlaying() :: 동영상 재생 완료]")
        print("====================================")
        print("")
        
        let alertView = UIAlertController(title: "동영상 재생", message: "동영상 재생이 완료되었습니다.", preferredStyle: .alert)
        alertView.addAction(UIAlertAction(title: "확인", style: .default, handler: nil))
        self.present(alertView, animated: true, completion: nil)
    }
    
    
} // [클래스 종료]
 

[결과 출력]

 

 

반응형
Comments