Identify when AVPlayerViewController is closed by tapping X button - ios

Is there any method to identify when we close the AVPlayerViewController when the video is still playing?
Attached the image as to which 'Close' button I am referring to.

try this :-
import UIKit
import AVKit
import AVFoundation
class VC: UIViewController {
var video_Url:String = String()
let playerController = AVPlayerViewController()
//MARK:- ViewDidload
override func viewDidLoad() {
super.viewDidLoad()
let player = AVPlayer(url: URL(string: video_Url)!)
playerController.player = player
self.present(playerController, animated: false) {
player.play()
self.playerController.addObserver(self, forKeyPath: #keyPath(UIViewController.view.frame), options: [.old, .new], context: nil)
}
}
override func viewDidDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
}
//MARK:- All Method
func playerDidFinishPlaying(note: NSNotification) {
self.navigationController?.popViewController(animated: false)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
self.playerController.removeObserver(self, forKeyPath: #keyPath(UIViewController.view.frame))
self.navigationController?.popViewController(animated: false)
}
}

Related

how to detect the changes of volume in iOS?

I‘ve read a lot solution provided by stackOverFlow and gitHub, and all of them doesn's work for me.I've tried the following tow way:
using audioSession
override func viewWillAppear(_ animated: Bool) {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true, options: [])
} catch {
print("error")
}
// this print shows, got the current volume.
//but what I need is the notification of the change of volume
print("view will appear ,this volume is \(audioSession.outputVolume)")
audioSession.addObserver(self,
forKeyPath: "outputVolume",
options: [.new],
context: nil)
}
override class func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
if keyPath == "outputVolume"{
let audioSession = AVAudioSession.sharedInstance()
let volume = audioSession.outputVolume
//this print doesn't shows up
print("observed volume is \(volume)")
}
}
using notification
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(observed(_:)), name: Notification.Name(rawValue: "AVSystemController_SystemVolumeDidChangeNotification"), object: nil)
}
#objc func observed(_ notification: Notification){
print("observed")
}
by the way, I'm using simulator(iPhone11, iOS13.1),Xcode version is 11.1
Try to use following:
import UIKit
import MediaPlayer
import AVFoundation
class ViewController: UIViewController {
private var audioLevel: Float = 0.0
deinit {
audioSession.removeObserver(self, forKeyPath: "outputVolume")
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
listenVolumeButton()
}
func listenVolumeButton() {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true, options: [])
audioSession.addObserver(self, forKeyPath: "outputVolume",
options: NSKeyValueObservingOptions.new, context: nil)
audioLevel = audioSession.outputVolume
} catch {
print("Error")
}
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "outputVolume" {
let audioSession = AVAudioSession.sharedInstance()
if audioSession.outputVolume > audioLevel {
print("Hello")
audioLevel = audioSession.outputVolume
}
if audioSession.outputVolume < audioLevel {
print("Goodbye")
audioLevel = audioSession.outputVolume
}
if audioSession.outputVolume > 0.999 {
(MPVolumeView().subviews.filter { NSStringFromClass($0.classForCoder) == "MPVolumeSlider" }.first as? UISlider)?.setValue(0.9375, animated: false)
audioLevel = 0.9375
}
if audioSession.outputVolume < 0.001 {
(MPVolumeView().subviews.filter { NSStringFromClass($0.classForCoder) == "MPVolumeSlider"}.first as? UISlider)?.setValue(0.0625, animated: false)
audioLevel = 0.0625
}
}
}
}
Hope this will help you!
You need to ensure your app's audio session is active for this to work:
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
startObservingVolumeChanges()
} catch {
print(“Failed to activate audio session")
}
So if all you need is to query the current system volume:
let volume = audioSession.outputVolume
Or we can be notified of changes like so:
private struct Observation {
static let VolumeKey = "outputVolume"
static var Context = 0
}
func startObservingVolumeChanges() {
audioSession.addObserver(self, forKeyPath: Observation.VolumeKey, options:
[.Initial, .New], context: &Observation.Context)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object:
AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>)
{
if context == &Observation.Context {
if keyPath == Observation.VolumeKey, let volume = (change?
[NSKeyValueChangeNewKey] as? NSNumber)?.floatValue {
// `volume` contains the new system output volume...
print("Volume: \(volume)")
}
} else {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change,
context: context)
}
}
Don't forget to stop observing before being deallocated:
func stopObservingVolumeChanges() {
audioSession.removeObserver(self, forKeyPath: Observation.VolumeKey,
context: &Observation.Context)
}

Observe a property from a viewController

I try to observe a property in a view controller, for example, isBeingDimissed property.. But It doesnt seem to work... Only when I set the options to .initial do I see that it works.
But I wanna observe new values.. Am I missing anything?
class ViewController: UIViewController {
var firstViewController = FirstViewController.init()
override func viewDidLoad() {
super.viewDidLoad()
firstViewController.addObserver(self, forKeyPath: #keyPath(UIViewController.isBeingPresented), options: .new, context: &myContext)
}
#IBAction func tapButton(_ sender: Any) {
present(firstViewController, animated: true, completion: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("let me see the change:", keyPath)
}
}

Detecting Click of Close button of AVPlayerViewController [duplicate]

This question already has answers here:
Done button click event in AVPlayerViewController
(9 answers)
Closed 3 years ago.
There is one functionality of Video playing Like linkedIn video playing.
i am using AVPlayerViewController for playing video.in that i am facing issue that i am not able to detect Close button event when AVPlayerviewController will close.
is there any Observer or method which will call when AVPlayerController will dismiss?
Swift 3.2
import UIKit
import AVKit
import AVFoundation
class PlayResourcesVC: UIViewController {
//MARK:- Variable Declarations
var video_Url:String = String()
let playerController = AVPlayerViewController()
//MARK:- ViewDidload
override func viewDidLoad() {
super.viewDidLoad()
let player = AVPlayer(url: URL(string: video_Url)!)
playerController.player = player
self.present(playerController, animated: false) {
player.play()
self.playerController.addObserver(self, forKeyPath: #keyPath(UIViewController.view.frame), options: [.old, .new], context: nil)
}
}
override func viewDidDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//MARK:- All Method
func playerDidFinishPlaying(note: NSNotification) {
self.navigationController?.popViewController(animated: false)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
self.playerController.removeObserver(self, forKeyPath: #keyPath(UIViewController.view.frame))
self.navigationController?.popViewController(animated: false)
}
}

Swift: Using Volume Buttons does not work after returning from Background

I needed to write an iOS App which counts down by pressing the Up Volume Key on an iPhone or iPad. Therefore I used some advice from here to use AVAudioSession and observe the "outputVolume" key.
Here you can find the code of my ViewController:
import UIKit
import MediaPlayer
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
#IBOutlet weak var chickenLabel: UILabel!
let audioSession = AVAudioSession.sharedInstance()
var maxHendl:Int = 100
var istHendl:Int = 100
var isVolumeChanged = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
listenVolumeButton()
removeVolumeView()
}
func listenVolumeButton() {
do {
try audioSession.setActive(true)
}
catch {
print(error.localizedDescription)
}
audioSession.addObserver(self, forKeyPath: "outputVolume", options: .new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "outputVolume" {
if isVolumeChanged == false {
// Set Volume to 50%
MPVolumeView().subviews.filter{NSStringFromClass($0.classForCoder) == "MPVolumeSlider"}.first as? UISlider)?.setValue(0.5, animated: false)
//do some Counting
}
}
}
func removeVolumeView() {
let volumeView: MPVolumeView = MPVolumeView(frame: CGRect.zero)
view.addSubview(volumeView)
}
}
Everything works as it should after starting the App for the first time. When I now press the Home Button and return back to the App the Events of pressing the volume buttons are not captured and the MPVolumeWindow is displayed again.
Can somebody help me to solve this issue?
Regards
Armin
When you come back from being in the background, your audio session is no longer active. You need to activate it again.

AVPlayerItemDidPlayToEndTimeNotification not firing

I am playing video from the url using AVPlayer. AVPlayerItemDidPlayToEndTimeNotification is not firing. I have put the breakpoints to check. Below is my code snippet:-
#IBAction func playButtonClicked(sender: UIButton) {
let url:NSURL = NSURL(string: self.currentSelectedContent.link)!
moviePlayer = AVPlayer(URL: url)
playerViewController = AVPlayerViewController()
playerViewController.player = moviePlayer
self.presentViewController(playerViewController, animated: true) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "moviePlayBackFinished", name: AVPlayerItemDidPlayToEndTimeNotification, object: self.moviePlayer)
self.playerViewController.player?.play()
}
}
func moviePlayBackFinished() {
self.playerViewController.dismissViewControllerAnimated(true, completion: nil)
}
According to the docs, the observed object must be the AVPlayerItem instance, not the AVPlayer itself. Try changing self.moviePlayer to self.moviePlayer.currentItem.
the property actionAtItemEnd of AVPlayer is KVO compliant:
moviePlayer.addObserver(self, forKeyPath: "actionAtItemEnd", options: [], context: nil)
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "actionAtItemEnd"{
//
print("FINISH")
}
}
https://developer.apple.com/documentation/avfoundation/avplayer/1387376-actionatitemend
https://developer.apple.com/documentation/avfoundation/avplayeractionatitemend
This works for me:
NotificationCenter.default.addObserver(self,
selector:#selector(didEndPlayback),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object:nil)

Resources