Volume Action. Обработка событий системной громкости для своих целей

Volume Action. Обработка событий системной громкости для своих целей

14:56:11 24.12.2015 akorotkov

Здравствуйте! Сегодня мы поговорим не столько о реализации какого-либо вопроса программирования, сколько об идее, реализовать которую можно в любой области, где подойдет ее концепция. Идея заключается в том, чтобы отлавливать изменения, в определенном порядке, системной громкости и обработки этого события по своему усмотрению. Надо заметить, что отлавливание событий системной громкости в разных системах может работать по-разному, поэтому применить ее в некоторых сценариях может не получится, например, на 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];

Все, теперь запускаем наш плеер, включаем трек и быстро меняем громкость - +. Так же это работает и в фоне, когда трек проигрывается.

Это очень простой пример использования данной идеи, но я надеюсь он даст вам пищу для размышлений и возможность добавить в вашу программу что-то полезное и удобное для ваших пользователей.

© 2002-2016 Креограф. Все права защищены законом РФ
 Русский /  English