티스토리 뷰

반응형

안녕하세요 Pingu입니다!

 

저번 글에서 음악이나 동영상을 백그라운드에서 재생 가능하도록 만들었습니다. 

그럼 이제 위와 같이 앱 외부에서 음악이나 동영상을 제어하는 방법을 알아보도록 하겠습니다!

우선 이번 글을 쓸 때 참고한 공식문서들입니다.

developer.apple.com/documentation/mediaplayer/mpremotecommandcenter 

developer.apple.com/documentation/mediaplayer/becoming_a_now_playable_app

 

일단 음악이나 동영상을 백그라운드에서 재생 가능하도록 만들었다고 가정하고 진행하겠습니다.

우선 MPRemoteCommandCenter, MPNowPlayingInfoCenter에 대해 알아보고 가도록 하겠습니다.

MPRemoteCommandCenter는 쉽게 말하면 버튼들을 눌렀을 때 어떤 이벤트를 발생할 거냐? 하는 거고요

MPNowPlayingInfoCenter는 위에 보면 show yourself에 대한 정보들이 적혀있죠? 현재 재생 중인 콘텐츠의 커버 사진이나 노래 제목, 아티스트와 같은 정보들을 처리하는 객체입니다.

 

얘네 둘을 사용하면 제어 센터에서 콘텐츠를 제어하고 정보를 확인할 수 있게 만들 수 있어요.

아! 그리고 얘네 둘은 MediaPlayer라는 라이브러리로 사용할 수 있습니다.

 

바로 한 번 사용해보겠습니다.

공식문서에 보시면, MPRemoteCommandCenter도 싱글 톤 객체라서 shared()라는 공유 객체에 작업을 해주시면 된다고 합니다. 그리고 중요한 건데 이러한 명령어를 받는 것을 시작하는 걸 앱에게 알려줘야 해요.

그건 이제 UIApplication의 인스턴스 메서드인 beginReceivingRemoteControlEvent()로 해줄 수 있습니다. 만약 remote command에 대한 이벤트를 더 이상 원하지 않으면 endReceivingRemoteControlEvents()로 중단할 수도 있습니다.

 

이런 것들을 고려해서 코드를 작성해보면... 아래와 같이 만들 수 있어요.

    func remoteCommandCenterSetting() {
        // remote control event 받기 시작
        UIApplication.shared.beginReceivingRemoteControlEvents()
        let center = MPRemoteCommandCenter.shared()
        
        // 제어 센터 재생버튼 누르면 발생할 이벤트를 정의합니다.
        center.playCommand.addTarget { (commandEvent) -> MPRemoteCommandHandlerStatus in
            self.player.play()
            return MPRemoteCommandHandlerStatus.success
        }
        
        // 제어 센터 pause 버튼 누르면 발생할 이벤트를 정의합니다.
        center.pauseCommand.addTarget { (commandEvent) -> MPRemoteCommandHandlerStatus in
            self.player.pause()
            return MPRemoteCommandHandlerStatus.success
        }
        
    }

그럼 이제 제어센터에서 제어가 됩니다. forward, backward 버튼은 설정을 안 해서 비활성화되어 있습니다.

다양한 제어 기능이 있는데 간단하게 play, pause만 사용했습니다.

 

근데 사진도 없고 이름도 이상하니 마음에 안 들기 때문에 얘네도 고쳐보겠습니다.

현재 재생중인 컨텐츠에 대한 정보는 NowPlayingInfoCenter라는 곳에서 관리하는데요, 얘도 싱글톤 디자인이라 미리 정의된 싱글톤 객체로 수정해주시면 됩니다.

func remoteCommandInfoCenterSetting() {
    let center = MPNowPlayingInfoCenter.default()
    var nowPlayingInfo = center.nowPlayingInfo ?? [String: Any]()
    
    nowPlayingInfo[MPMediaItemPropertyTitle] = "콘텐츠 제목"
    nowPlayingInfo[MPMediaItemPropertyArtist] = "콘텐츠 아티스트"
    if let albumCoverPage = UIImage(named: "Pingu") {
        nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: albumCoverPage.size, requestHandler: { size in
            return albumCoverPage
        })
    }
    // 콘텐츠 총 길이
    nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = player.duration
    // 콘텐츠 재생 시간에 따른 progressBar 초기화
    nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
    // 콘텐츠 현재 재생시간
    nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player.currentTime
    
    center.nowPlayingInfo = nowPlayingInfo
    
}

위와 같이 잘 수정되는 것을 볼 수 있습니다.

 

근데 얘네가 싱글 톤으로 되어있다 보니 다른 뷰 컨트롤러에서 이를 바꿔버리면 다시 돌아왔을 때 얘네에 대한 제어가 사라질 수 있습니다. 그래서 적절하게 뷰의 life cycle에 맞게 잘 처리를 해줘야 콘텐츠를 제어센터에서 잘 제어할 수 있게 됩니다.

 

또한 remote command를 적절할 때 제거하지 않으면 여러개 중첩되는 문제도 있었습니다.

 

물론 콘텐츠가 하나라서 걱정할 필요가 없다면 문제가 없겠지만요!

 

얘네는 백그라운드에서도 잘 작동하기 때문에 다양하게 활용할 수 있을 거 같아요!

 

감사합니다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함