Is There a Public Way to Force Mpnowplayinginfocenter to Show Podcast Controls

Is there a public way to force MPNowPlayingInfoCenter to show podcast controls?

OK so I had a bit of time on my hands and so I followed the breadcrumb.…
This is what I found.

Include the MediaPlayer framework and get hold of the RemoteCommandCenter:

MPRemoteCommandCenter *rcc = [MPRemoteCommandCenter sharedCommandCenter];

then if you wanted to set the skip controls as per Overcast you can do the following:

MPSkipIntervalCommand *skipBackwardIntervalCommand = [rcc skipBackwardCommand];
[skipBackwardIntervalCommand setEnabled:YES];
[skipBackwardIntervalCommand addTarget:self action:@selector(skipBackwardEvent:)];
skipBackwardIntervalCommand.preferredIntervals = @[@(42)]; // Set your own interval

MPSkipIntervalCommand *skipForwardIntervalCommand = [rcc skipForwardCommand];
skipForwardIntervalCommand.preferredIntervals = @[@(42)]; // Max 99
[skipForwardIntervalCommand setEnabled:YES];
[skipForwardIntervalCommand addTarget:self action:@selector(skipForwardEvent:)];

and in the event handlers do what you need to do to skip by the interval:

-(void)skipBackwardEvent: (MPSkipIntervalCommandEvent *)skipEvent
{
NSLog(@"Skip backward by %f", skipEvent.interval);
}

-(void)skipForwardEvent: (MPSkipIntervalCommandEvent *)skipEvent
{
NSLog(@"Skip forward by %f", skipEvent.interval);
}

Note: The preferredIntervals property is an NSArray but I haven’t figured out how extra intervals can be utilised by the command center unless you do something with this yourself.

Things to note that I’ve found so far. When you do this you are taking control of all the controls so the default play and pause buttons won't show unless you do the same for them:

MPRemoteCommand *pauseCommand = [rcc pauseCommand];
[pauseCommand setEnabled:YES];
[pauseCommand addTarget:self action:@selector(playOrPauseEvent:)];
//
MPRemoteCommand *playCommand = [rcc playCommand];
[playCommand setEnabled:YES];
[playCommand addTarget:self action:@selector(playOrPauseEvent:)];

(there is also a togglePlayPauseCommand defined but I could’t get this to fire from the Command Centre - it does fire from headphones though.)

Other discoveries:
The buttons are in fixed positions left / middle / right so you cant have (for example) a previousTrack and a skipBackward as they both occupy the left position.

There are seekForward / seekBackward commands that need a prevTrack and nextTrack command to be triggered. When you set up both then a single tap triggers next / previous and a press and hold triggers a begin seek and an end seek when you lift your finger.

    // Doesn’t show unless prevTrack is enabled
MPRemoteCommand *seekBackwardCommand = [rcc seekBackwardCommand];
[seekBackwardCommand setEnabled:YES];
[seekBackwardCommand addTarget:self action:@selector(seekEvent:)];

// Doesn’t show unless nextTrack is enabled
MPRemoteCommand *seekForwardCommand = [rcc seekForwardCommand];
[seekForwardCommand setEnabled:YES];
[seekForwardCommand addTarget:self action:@selector(seekEvent:)];

-(void) seekEvent: (MPSeekCommandEvent *) seekEvent
{
if (seekEvent.type == MPSeekCommandEventTypeBeginSeeking) {
NSLog(@"Begin Seeking");
}
if (seekEvent.type == MPSeekCommandEventTypeEndSeeking) {
NSLog(@"End Seeking");
}
}

There is also a feedback mechanism that I haven’t seen before (occupies left position)

    MPFeedbackCommand *likeCommand = [rcc likeCommand];
[likeCommand setEnabled:YES];
[likeCommand setLocalizedTitle:@"I love it"]; // can leave this out for default
[likeCommand addTarget:self action:@selector(likeEvent:)];

MPFeedbackCommand *dislikeCommand = [rcc dislikeCommand];
[dislikeCommand setEnabled:YES];
[dislikeCommand setActive:YES];
[dislikeCommand setLocalizedTitle:@"I hate it"]; // can leave this out for default
[dislikeCommand addTarget:self action:@selector(dislikeEvent:)];

BOOL userPreviouslyIndicatedThatTheyDislikedThisItemAndIStoredThat = YES;

if (userPreviouslyIndicatedThatTheyDislikedThisItemAndIStoredThat) {
[dislikeCommand setActive:YES];
}

MPFeedbackCommand *bookmarkCommand = [rcc bookmarkCommand];
[bookmarkCommand setEnabled:YES];
[bookmarkCommand addTarget:self action:@selector(bookmarkEvent:)];

// Feedback events also have a "negative" property but Command Center always returns not negative
-(void)dislikeEvent: (MPFeedbackCommandEvent *)feedbackEvent
{
NSLog(@"Mark the item disliked");
}

-(void)likeEvent: (MPFeedbackCommandEvent *)feedbackEvent
{
NSLog(@"Mark the item liked");
}

-(void)bookmarkEvent: (MPFeedbackCommandEvent *)feedbackEvent
{
NSLog(@"Bookmark the item or playback position");
}

This displays three horizontal bars and brings up an alert sheet - you can highlight these individually by setting the active property.

There is also a rating command defined - but I couldn't get this to show in the Command Center

//    MPRatingCommand *ratingCommand = [rcc ratingCommand];
// [ratingCommand setEnabled:YES];
// [ratingCommand setMinimumRating:0.0];
// [ratingCommand setMaximumRating:5.0];
// [ratingCommand addTarget:self action:@selector(ratingEvent:)];

and a playback rate change command - but again couldn’t get this to show in Command Center

//    MPChangePlaybackRateCommand *playBackRateCommand = [rcc changePlaybackRateCommand];
// [playBackRateCommand setEnabled:YES];
// [playBackRateCommand setSupportedPlaybackRates:@[@(1),@(1.5),@(2)]];
// [playBackRateCommand addTarget:self action:@selector(remoteControlReceivedWithEvent:)];

There is also a block-based target action mechanism if you prefer

// @property (strong, nonatomic) id likeHandler;
self.likeHandler = [likeCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent *event) {
NSLog(@"They like it");
return MPRemoteCommandHandlerStatusSuccess; // or fail or no such content
}];

One final point to be aware of: If you have registered to receive remote events via [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; then some of these commands also trigger events in the - (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent handler. These are UIEvents though with type UIEventTypeRemoteControl and a subtype to distinguish the event. You can't mix and match these with MPRemoteCommandEvents in this method. There are hints that MPRemoteCommandEvents will replace the UIEvents at some point.

All of this based on trial and error so feel free to correct.

Gareth

Screenshot of feedback command and skipforward

How to disable all the MPRemoteCommand objects from MPRemoteCommandCenter

Yes "you can disable the corresponding MPRemoteCommand object by setting its enabled property to NO."

But If you are disabling all the buttons then don't remove the target or add a target which will probably do nothing. There is no document explaining why we have to do this but it works this way.

Try the following code this will work.

MPRemoteCommandCenter *remoteCommandCenter = [MPRemoteCommandCenter sharedCommandCenter];
remoteCommandCenter.previousTrackCommand.enabled = NO;
remoteCommandCenter.nextTrackCommand.enabled = NO;
remoteCommandCenter.skipBackwardCommand.enabled = NO;
remoteCommandCenter.skipForwardCommand.enabled = NO;
remoteCommandCenter.bookmarkCommand.enabled = NO;
remoteCommandCenter.playCommand.enabled = NO;
remoteCommandCenter.pauseCommand.enabled = NO;

[remoteCommandCenter.previousTrackCommand addTarget:self action:@selector(actionDoNothing:)];
[remoteCommandCenter.nextTrackCommand addTarget:self action:@selector(actionDoNothing:)];
[remoteCommandCenter.skipBackwardCommand addTarget:self action:@selector(actionDoNothing:)];
[remoteCommandCenter.skipForwardCommand addTarget:self action:@selector(actionDoNothing:)];
[remoteCommandCenter.bookmarkCommand addTarget:self action:@selector(actionDoNothing:)];
[remoteCommandCenter.playCommand addTarget:self action:@selector(actionDoNothing:)];
[remoteCommandCenter.pauseCommand addTarget:self action:@selector(actionDoNothing:)];

How to add seek buttons on iOS lock screen?

You would also need to set preferredIntervals as described in https://stackoverflow.com/a/24818340/1514970.

Can I hide the rewind button in the iOS Lock Screen Music controls?

As of iOS 7.1 there is a way to customize the controls available in the lock screen and command center (and probably many other accessories): MPRemoteCommandCenter.

Regarding your question you can do the following:

[MPRemoteCommandCenter sharedCommandCenter].previousTrackCommand.enabled = NO;
[MPRemoteCommandCenter sharedCommandCenter].skipBackwardCommand.enabled = NO;
[MPRemoteCommandCenter sharedCommandCenter].seekBackwardCommand.enabled = NO;

// You must also register for any other command in order to take control
// of the command center, or else disabling other commands does not work.
// For example:
[MPRemoteCommandCenter sharedCommandCenter].playCommand.enabled = YES;
[[MPRemoteCommandCenter sharedCommandCenter].playCommand addTarget:self action:@selector(play)];

Please see this Stack Overflow answer for more general information about MPRemoteCommandCenter.

Managing AVSpeechSynthesizer's execution via system playback controls

Ok, after a while I found the answer. If somebody else is interested there is MPRemoteCommandCenter class which does the business. Enjoy your coding.



Related Topics



Leave a reply



Submit