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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With