I have found the solution to what I thought would be a common problem. So here is how your app can have its own volume, and not mess with the user's ringer volume, even if you are only playing sounds as System Sounds.
You have to import the AVFoundation framework and in an object that stays loaded the whole time your app runs (or view, or the app delegate) you have initialize a AVAudioPlayer, give it a file to play and set it to "prepareToPlay" it...
This is what i did in my main View (that is used to load other views as subviews):
in the header file:
#import <AVFoundation/AVFoundation.h>
@interface MainViewController : UIViewController {
AVAudioPlayer *volumeOverridePlayer;
}
@property (nonatomic, retain) AVAudioPlayer *volumeOverridePlayer;
In the implementation file:
@synthesize volumeOverridePlayer;
- (void)viewDidLoad
{
[super viewDidLoad];
volumeOverridePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"something" ofType:@"caf"]] error:nil];
[volumeOverridePlayer prepareToPlay];
//...
}
Just leave the player prepared to play your file and enjoy your own volume control without having to play the sounds through it!
And of course, remember to release it in dealloc.