objective c - Play/Pause and Elapsed Time not updating in iOS command center properly -
i have video player can play ios command center , lock screen. when toggle play/pause button in app, should update play/pause button in command center (mpremotecommandcenter
) updating nowplayinginfo
(mpnowplayinginfocenter
). i'm not sure why it's not updating.
for example, if pause video custom button in app, command center still shows pause button (meaning video still playing wrong.)
this how update nowplayinginfo
:
func updatempnowplayinginforcentermetadata() { guard video != nil else { nowplayinginfocenter.nowplayinginfo = nil return } var nowplayinginfo = nowplayinginfocenter.nowplayinginfo ?? [string: any]() let image: uiimage if let placeholderlocalurl = video.placeholderlocalurl, let placeholderimage = uiimage(contentsoffile: placeholderlocalurl.path) { image = placeholderimage } else { image = uiimage() } let artwork = mpmediaitemartwork(boundssize: image.size, requesthandler: { _ -> uiimage in return image }) nowplayinginfo[mpmediaitempropertytitle] = video.title nowplayinginfo[mpmediaitempropertyalbumtitle] = video.creator?.name ?? " " nowplayinginfo[mpmediaitempropertyartwork] = artwork nowplayinginfo[mpmediaitempropertyplaybackduration] = float(video.duration) nowplayinginfo[mpnowplayinginfopropertyelapsedplaybacktime] = float(currenttime) // cmtimegetseconds(player.currentitem!.currenttime()) nowplayinginfo[mpnowplayinginfopropertyplaybackrate] = player.rate nowplayinginfo[mpnowplayinginfopropertydefaultplaybackrate] = player.rate nowplayinginfocenter.nowplayinginfo = nowplayinginfo if player.rate == 0.0 { state = .paused } else { state = .playing } }
with kvo, when player's rate
changes, call function:
// mark: - key-value observing method override func observevalue(forkeypath keypath: string?, of object: any?, change: [nskeyvaluechangekey : any]?, context: unsafemutablerawpointer?) { guard context == &assetplaybackmanagerkvocontext else { super.observevalue(forkeypath: keypath, of: object, change: change, context: context) return } } else if keypath == #keypath(avplayer.rate) { updatempnowplayinginforcentermetadata() } }
any thoughts?
update
i found solution though not perfect in case. in app have 2 view controller's. let's call them feedvc
, playervc
. feedvc
has avplayer
's playing muted. if click on 1 of them, playervc
created , plays full video. if pause avplayer
's in feedvc
before going playervc
"play/pause" button in nowplayinginfocenter works perfectly!
is there way make work without having pause videos in feedvc
?
another issue elapsed time
keeps counting if don't pause players in feedvc
. seems if multiple players playing, play/pause button , elapsed time incorrect.
when setting dictionary nowplayinginfo
want set mpnowplayinginfopropertyplaybackrate
value appropriately. mpnowplayinginfocenter
expecting either 1.0
(playing) or 0.0
(not playing) value double
wrapped in nsnumber
object. below find code how i'm setting nowplayinginfo
in project.
func setnowplayingmediawith(song: susong, currenttime: double?) { var playinginfo:[string: any] = [:] if let title = song.title { playinginfo[mpmediaitempropertytitle] = title } if let songid = song.id { playinginfo[mpmediaitempropertypersistentid] = songid } if let artist = song.artist, let artistname = artist.name { playinginfo[mpmediaitempropertyartist] = artistname } if let album = song.album, let albumtitle = album.title { var artwork:mpmediaitemartwork? = nil if let album = song.album, let artworkdata = album.artwork { artwork = mpmediaitemartwork(boundssize: constants.library.albums.thumbsize, requesthandler: { (size) -> uiimage in return uiimage(data: artworkdata data)! }) } if artwork != nil { playinginfo[mpmediaitempropertyartwork] = artwork! } playinginfo[mpmediaitempropertyalbumtitle] = albumtitle } var rate:double = 0.0 if let time = currenttime { playinginfo[mpnowplayinginfopropertyelapsedplaybacktime] = time playinginfo[mpmediaitempropertyplaybackduration] = song.duration rate = 1.0 } playinginfo[mpnowplayinginfopropertyplaybackrate] = nsnumber(value: rate) playinginfo[mpnowplayinginfopropertymediatype] = nsnumber(value: mpnowplayinginfomediatype.audio.rawvalue) mpnowplayinginfocenter.default().nowplayinginfo = playinginfo }
in method passing song
player has loaded. whenever user chooses play or pause call setnowplayingmediawith(song:currenttime:)
update device's control console.
i keep track of currenttime
(double
) property of player. if there currenttime
passed in means meant playing, set mpnowplayinginfopropertyplaybackrate
1.0
, set mpnowplayinginfopropertyelapsedplaybacktime
currenttime
. set current time start automatically playing in device's control console.
likewise, if there no currenttime
passed have stopped or paused. in case set mpnowplayinginfopropertyplaybackrate
0.0
, not include mpnowplayinginfopropertyelapsedplaybacktime
.
download app see in action.
edit (answer comments)
"is there way make work without having pause videos in feedvc"
without seeing code difficult give definite answer. make sense though pause ongoing media before starting playervc
's media.
"the elapsed time keeps counting"
the elapsed time countdown elapsed time based on nstimer
property on nowplayinginfocenter
. timer stop when timers value has reached value set in mpmediaitempropertyplaybackduration
, or when update mpnowplayinginfopropertyelapsedplaybacktime
.
my suggestion write method "clears out" nowplayinginfocenter
. method should set set of key values either 0.0 or nil respectively. call "clear out" method each time before play media in playervc
. once play playervc
, set nowplayinginfocenter
key values in method pasted in answer set new values new playing media.
Comments
Post a Comment