Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change metadata for AVRoutePickerView?

enter image description here

My app plays some sound and I implemented AVRoutePickerView so it can stream its sound through AirPlay or Bluetooth.

Once I tap the AVRoutePickerView, above image pops up which is good, however, with wrong image and title.

The image and title came from Apple Music app I played before.

How can I change this metadata?

I've tried configuring MPNowPlayingInfoCenter without luck.

let albumArt = MPMediaItemArtwork(boundsSize:CGSize(width: 50, height: 50)) { sz in
    return UIImage(named: "MyImage")!
}

MPNowPlayingInfoCenter.default().nowPlayingInfo = [MPMediaItemPropertyTitle: "some title",
                                               MPMediaItemPropertyArtist: "some artist",
                                               MPMediaItemPropertyArtwork: albumArt]

And this is how I made AVRoutePickerView.

import AVKit

let routePickerView = AVRoutePickerView.init(frame: myFrame)
routePickerView.backgroundColor = UIColor.clear
routePickerView.tintColor = UIColor(named: someColor)
routePickerView.activeTintColor = UIColor(named: someColor)
soundController.contentView.addSubview(routePickerView)

My app targets iOS11 and testing on iPhone 6 and iPhone 7.

Please guide me to the right way. Thanks

like image 666
Vincent Gigandet Avatar asked Apr 26 '18 20:04

Vincent Gigandet


1 Answers

>> UPDATE <<
As well as providing Now Playing information using the MPNowPlayingInfoCenter object, it seems you need to setup remote event handlers (even if not used) using the MPRemoteCommandCenter object.
Also, the Now Playing info doesn't seem to update until audio is played by the app.

Steps:

1. Setup the Remote control event handlers.
In this example I have only configured the pauseCommand, as that was all that was needed to get the Now Playing info to work.

func setupRemoteTransportControls() {
    // Get the shared MPRemoteCommandCenter
    let commandCenter = MPRemoteCommandCenter.shared()

    // Add handler for Pause Command
    commandCenter.pauseCommand.addTarget{ event in
           // Does nothing yet
           return .success
    }

}


2. Configure the Now Playing information using the MPNowPlayingInfoCenter object.

func setupNowPlayingInfo() {

    var nowPlayingInfo = [String : Any]()
    nowPlayingInfo[MPMediaItemPropertyTitle] = "My Song Title"

    if let image = UIImage(named: "MyImage") {
        nowPlayingInfo[MPMediaItemPropertyArtwork] =
            MPMediaItemArtwork(boundsSize: image.size) { size in return image }
    }

    MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}


3. Create the Route Picker view control.

let routePickerView = AVRoutePickerView(frame: routView.bounds)
routePickerView.backgroundColor = UIColor.clear
routView.addSubview(routePickerView)


4. Play the audio and view the route picker.

If you view the route picker before playing the app audio, the old now playing info will remain.

Hope this works now!



OLD ANSWER
Your implementation looks ok. The only query would be the boundSize. It should be the original size of the artwork. From the manual: "The request handler returns an image in the newly requested size. The requested size must be less than the boundsSize parameter." It seems most implementations just return the original size.

Perhaps it is your implementation of AVRoutePickerView where the problem lies. Could you try putting it inside a dispatch queue?

DispatchQueue.main.async { 
    let albumArt = MPMediaItemArtwork(boundsSize:CGSize(width: 50, height: 50)) 
                    { sz in return UIImage(named: "MyImage")!}

    MPNowPlayingInfoCenter.default().nowPlayingInfo = 
        [MPMediaItemPropertyTitle: "some title", 
         MPMediaItemPropertyArtist: "some artist", 
         MPMediaItemPropertyArtwork: albumArt]
}

In my audio streaming application I provide the meta data for display in the Control Center and iOS Lock screen when the app is in background. I use the MPVolumeView which has a button for choosing the audio output route (automatically handles instantiation and display of an AVRoutePickerView).

My implemention is as follows (as per manual):

var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = "Song Title"
nowPlayingInfo[MPMediaItemPropertyArtist] = "Song Artist"

if let image = UIImage(named: "SongImage") {
    nowPlayingInfo[MPMediaItemPropertyArtwork] =  MPMediaItemArtwork(boundsSize: image.size) { size in return image }
}

MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
like image 155
David Mayes Avatar answered Oct 21 '22 10:10

David Mayes