How do I turn the system volume overlay back on after using MPVolumeView?

IphoneIosMedia Player

Iphone Problem Overview


I'm building an audio player for a non-native sound format. The application's hierarchy is based on the iPod.app. It has a number of UITableView's and one UIView (TrackView) that uses an MPVolumeView to allow the user to change the volume onscreen. Until the first time TrackView becomes visible changing the volume using the hardware buttons displays the system volume overlay as expected (and desired). When TrackView is visible these overlays don't appear since the MPVolumeView updates when changing the volume with the hardware buttons (also desired).

Here's the problem: once you back out of TrackView the system volume overlay does not appear when using the hardware volume buttons. I have tried programmatically allocing, creating and adding the MPVolumeView in TrackViewController viewWillAppear: and then removing, releasing and nil-ing the same MPVolumeView in TrackViewController viewWillDisappear:.

This does not happen in the iPod.app. Once backing out of the view that contains an MPVolumeView the system volume overlays display when using the hardware volume buttons.

What am I missing?


Update 2: This appears to be a bug in MPVolumeView that was introduced sometime after iOS 3.2 and fixed in 4.2.


Update: I made a simple reduction from the default window-based application project that exhibits the same behavior. Once an MPVolumeView becomes visible the system volume overlays are never seen in the application again.

VolumeAppDelegate.h:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>

@interface VolumeAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
	IBOutlet UIView *volumeView;
	IBOutlet MPVolumeView *mpVolumeView;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

-(IBAction)toggleVolumeView:(id)sender;

@end

VolumeAppDelegate.m:

#import "VolumeAppDelegate.h"

@implementation VolumeAppDelegate

@synthesize window;

-(IBAction)toggleVolumeView:(id)sender{

	if (mpVolumeView == nil){
		mpVolumeView = [[MPVolumeView alloc] initWithFrame:volumeView.bounds];
		[volumeView addSubview:mpVolumeView];
	}
	else{
		[mpVolumeView removeFromSuperview];
		[mpVolumeView release];
		mpVolumeView = nil;
	}
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    [self.window makeKeyAndVisible];
	mpVolumeView = nil;
    return YES;
}

- (void)dealloc {
    [window release];
    [super dealloc];
}

@end

You'll need to add the MediaPlayer framework to your project in Xcode and open up MainWindow.xib in Interface builder to add the UIView and UIButton IBOutlets and hookup the IBAction to the UIButton.

Iphone Solutions


Solution 1 - Iphone

This is sadly an issue with the private framework in the earlier versions of iOS.

I understand your wish to make a solution for this, but it would cause your code to manipulate the private framework, making your app unable to pass approval.

Fortunately, the version span that had this error is short, and the number of devices in circulation with these version are growing thinner by the minute.

Solution 2 - Iphone

You can increase and decrease device volume by programmatically like:

- (void)setVolume:(float)Level
{

   OSStatus errorMsg = AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, Level);

   if (errorMsg) {
      NSLog(@"%d", errorMsg);
   }

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionShaun InmanView Question on Stackoverflow
Solution 1 - IphoneNils MunchView Answer on Stackoverflow
Solution 2 - IphoneBipin PatelView Answer on Stackoverflow