Volume Action. Обработка событий системной громкости для своих целей
Здравствуйте! Сегодня мы поговорим не столько о реализации какого-либо вопроса программирования, сколько об идее, реализовать которую можно в любой области, где подойдет ее концепция. Идея заключается в том, чтобы отлавливать изменения, в определенном порядке, системной громкости и обработки этого события по своему усмотрению. Надо заметить, что отлавливание событий системной громкости в разных системах может работать по-разному, поэтому применить ее в некоторых сценариях может не получится, например, на iPhone событие изменения громкости можно отловить, только когда приложение активно либо когда оно в фоне играет какую-либо музыку (по крайней мере я решения данной проблемы не нашел, но мне особой необходимости в этом не было, так что вам все карты в руки).
Представьте ситуацию, что вы идете по улице, слушаете музыку в своем любимом плеере на iPhone. Сам телефон в кармане. Вдруг играет песня, которая вам очень понравилась, и вы хотите ее как-то отметить, поставить оценку, добавить в определенный альбом и прочее, что может ваш любимый плеер. Для этого вам необходимо достать телефон, разблокировать и сделать необходимые манипуляции. А теперь представьте, что этот плеер уже реализовал идею VolumeAction и для произведения нужных вам манипуляций с играющим треком вам нужно на гарнитуре всего лишь убавить громкость (-) и сразу быстро ее назад прибавить (+).
В данной статье мы и разберем эту идею на примере простенького плеера для iPhone, который будет добавлять название играющей в фоне песни в текстовое поле при нажатии на - +.
Для начала откроем Xcode и создадим новый проект Single View Application.
Назовем его, например, VolumeActionTest и сохраним.
Положите на наш View Controller три UIButton и назовите их как показано на рисунке, либо по вашему усмотрению. А также UILabel для отображения названия трека и UITextView куда мы будем добавлять выбранные треки с его заголовком в виде UILabel.
Теперь нужно создать связи наших объектов на View Controller с модулем его класса. Для этого в ViewController.h создайте два IBOutlet:
@property (strong, nonatomic) IBOutlet UILabel *trackNameLabel; @property (strong, nonatomic) IBOutlet UITextView *addedTracksTextView;
Перейдите назад в Storyboard, выберите режим Assistant Editor, в котором экран делится на две области, выберите ViewController.h в области кода (если она не выбралась автоматически) и правой кнопкой мыши протяните от UILabel для названия трека к IBOutlet UILabel *trackNameLabel в ViewController.h. Сделайте то же самое с UITextView, куда мы будем добавлять треки.
Добавьте в проект несколько mp3 треков простым перетягиванием их в Project Navigator и задайте им удобоваримые имена.
Теперь пока перейдем к написанию кода. Откройте ViewController.m.
Импортируйте заголовки следующих фреймворков:
#import <MediaPlayer/MPMusicPlayerController.h>
#import <AVFoundation/AVFoundation.h>
Объявите переменные:
NSArray* tracksArray; //массив наших треков NSInteger currentTrack = 0; //индекс активного трека AVAudioPlayer *audioPlayer; //аудиоплеер
В методе (void)viewDidLoad, который вызывается при инициализации ViewController, создадим аудиосессию, чтобы музыка продолжала играть в фоне:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; [[AVAudioSession sharedInstance] setActive: YES error: nil];
Создадим массив наших треков (подставьте свои имена треков):
tracksArray = @[@"Problem Child", @"Marimba Take Two", @"Rock RingingTone", @"Twinkle Twinkle"];
А также загрузим первый трек, но пока не проигрываем его
[self loadTrack:currentTrack andPlay:NO];
Далее, добавим метод включения трека:
-(void)loadTrack:(NSInteger)trackIndex andPlay:(BOOL)play { audioPlayer = nil; NSURL *audioFileLocationURL = [[NSBundle mainBundle] URLForResource:tracksArray[trackIndex] withExtension:@"mp3"]; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileLocationURL error:nil]; [audioPlayer prepareToPlay]; [_trackNameLabel setText:tracksArray[trackIndex]]; if (play) { [audioPlayer play]; } }
И методы Старта/Паузы и переключения трека:
- (IBAction)playPrevNext:(UIButton *)sender { if (sender.tag==0) { currentTrack = (currentTrack>0) ? currentTrack-1 : tracksArray.count-1; } else { currentTrack = (currentTrack==tracksArray.count-1) ? 0: currentTrack+1; } [self loadTrack:currentTrack andPlay:YES]; } - (IBAction)playPauseButton:(UIButton *)sender { if (!audioPlayer.playing) { [audioPlayer play]; } else if (audioPlayer.playing) { [audioPlayer pause]; } }
Последние методы нужно соединить с кнопками в нашем View Controller. Укажите значение свойства tag у кнопки Prev равного 0, а у кнопки Next равного 1. Теперь, таким же способом, как мы соединяли наши UILabel и UITextView, соедините кнопки Prev и Next с методом (IBAction)playPrevNext, а кнопку Play/Pause с методом (IBAction)playPauseButton.
На данном этапе наш плеер уже должен работать, играть музыку, переключать треки. Можно запустить и проверить.
Теперь перейдем непосредственно к созданию Volume Action.
Объявите новые переменные:
CGFloat lastVolumeForAction; //последняя громкость, которую будем сравнивать с текущей, чтобы отловить порядок изменения CGFloat currentVolumeForAction; //текущая громкость BOOL volumeActionWaiting = NO; //флаг ожидания завершения очереди клавиш
Добавьте метод сброса ожидания очереди клавиш:
-(void)resetLastVolumeForAction { volumeActionWaiting = NO; lastVolumeForAction = currentVolumeForAction; NSLog(@"resetLastVolumeForAction"); }
Добавьте метод обработки событий изменения системной громкости:
-(void)startVolumeObserver
{
[[MPMusicPlayerController iPodMusicPlayer] beginGeneratingPlaybackNotifications];
[[NSNotificationCenter defaultCenter]addObserverForName:MPMusicPlayerControllerVolumeDidChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note)
{
MPMusicPlayerController * musicPlayerController = note.object;
currentVolumeForAction = musicPlayerController.volume;
if (currentVolumeForAction {
lastVolumeForAction = currentVolumeForAction;
volumeActionWaiting = YES;
NSInteger waitingTime = 0.5; //здесь указываем сколько секунд ждать следующей клавиши в очереди
[NSTimer scheduledTimerWithTimeInterval:waitingTime
target:self
selector:@selector(resetLastVolumeForAction)
userInfo:nil
repeats:NO];
}
else
{
if (volumeActionWaiting)
{
NSLog(@"Volume Action!");
[self volumeAction];
}
[self resetLastVolumeForAction];
}
}];
}
И непосредственно сам VolumeForAction:
-(void)volumeAction { [_addedTracksTextView setText:[NSString stringWithFormat:@"%@\n%@", tracksArray[currentTrack], _addedTracksTextView.text]]; }
Осталось только добавить метод обработки событий изменения системной громкости в наш метод (void)viewDidLoad:
[self startVolumeObserver];
Все, теперь запускаем наш плеер, включаем трек и быстро меняем громкость - +. Так же это работает и в фоне, когда трек проигрывается.
Это очень простой пример использования данной идеи, но я надеюсь он даст вам пищу для размышлений и возможность добавить в вашу программу что-то полезное и удобное для ваших пользователей.