Как реализовать кнопку громкости затвора для iPhone? - PullRequest
20 голосов
/ 06 декабря 2011

Я хочу реализовать то же поведение с родной камерой iOS5:

  • нажмите кнопку громкости +, чтобы сделать фотографию

Чтоидеальный способ заархивировать его?Есть ли способы зафиксировать событие нажатия клавиши громкости?

После поиска и поиска в течение нескольких часов я нашел одно решение: используя NSNotificationCenter:

...
    [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(volumeChanged:)
         name:@"AVSystemController_SystemVolumeDidChangeNotification"
         object:nil];
...
- (void)volumeChanged:(NSNotification *)notification{
    [self takePhoto];   
}

Однако,у него есть 2 проблемы:

  • При каждом нажатии клавиши громкости появляется полупрозрачная накладка «текущая громкость системы», это не то, что я хотел.
  • Для родной камеры, когда вы нажимаете клавишу громкости в качестве затвора, громкость системы не изменится, однако при использовании описанного выше способа громкость системы изменится.

Ответы [ 5 ]

12 голосов
/ 06 декабря 2011

Я нашел другой способ скрыть «оверлей громкости системы» и «обойти изменение громкости системы при нажатии клавиши громкости» самостоятельно.

Плохая часть: это супер Гадкий хак.

Однако, хорошая часть заключается в следующем: этот безобразный хакер не использует никаких закрытых API.

Еще одно замечание: это работает только для ios5 + (во всяком случае, для моей проблемы, так как AVSystemController_SystemVolumeDidChangeNotification работает только для ios5, поэтому этот Гадкий хак как раз подходит моей проблеме.)

Как это работает: «выступать в качестве приложения для воспроизведения музыки / фильмов и позволить клавише громкости регулировать громкость приложения».

Код:

// these 4 lines of code tell the system that "this app needs to play sound/music"
AVAudioPlayer* p = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"photo-shutter.wav"]] error:NULL];
[p prepareToPlay];
[p stop];
[p release];

// these 5 lines of code tell the system that "this window has an volume view inside it, so there is no need to show a system overlay"
[[self.view viewWithTag:54870149] removeFromSuperview];
MPVolumeView* vv = [[MPVolumeView alloc] initWithFrame:CGRectMake(-100, -100, 100, 100)];
[self.view addSubview:vv];
vv.tag = 54870149;
[vv release];

(5 часов на изучение этого супер уродливого метода ... дерьмо ... 草 尼马 啊!)

Другое дело: если вы воспользуетесь вышеуказанным хаком, вам нужно запускать код КАЖДЫЙ раз, когда ваше приложение станет активным. Таким образом, вам может понадобиться добавить некоторый код в делегат приложения.

- (void)applicationDidBecomeActive:(UIApplication *)application 
12 голосов
/ 05 мая 2012

Опираясь на код huxia, это работает на ios5 +, нет необходимости запускать код каждый раз, когда он становится активным, просто запустите его один раз в начале.

// these 4 lines of code tell the system that "this app needs to play sound/music"
AVAudioPlayer* p = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"photoshutter.wav"]] error:NULL];
[p prepareToPlay];
[p stop];

//make MPVolumeView Offscreen
CGRect frame = CGRectMake(-1000, -1000, 100, 100);
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:frame];
[volumeView sizeToFit];
[self.view addSubview:volumeView];
3 голосов
/ 10 сентября 2012

[[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(volumeChanged:)
     name:@"AVSystemController_SystemVolumeDidChangeNotification"
     object:nil];

- (void)volumeChanged:(NSNotification *)notification{ 

    CGRect frame = CGRectMake(-1000, -1000, 100, 100);
    MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:frame];
    [volumeView sizeToFit];
    [self.view addSubview:volumeView];
    [volumeView release];

    [self takePhoto];   
}
2 голосов
/ 09 февраля 2015

Я вызываю этот метод из viewDidAppear

-(void) startTrackingVolume
{
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
    [[AVAudioSession sharedInstance] setActive:YES error:nil];

    if (!self.volumeView) {
        // put it somewhere outside the bounds of parent view
        self.volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(-100, -100, 10, 0)];
        [self.volumeView sizeToFit];
    }

    if (!self.volumeView.superview) {
        [self.view addSubview:self.volumeView];
    }
}

В viewWillDisappear при вызове

[[AVAudioSession sharedInstance] setActive:NO error:nil];
2 голосов
/ 06 декабря 2011

В настоящее время нет официального способа зафиксировать событие нажатия клавиши громкости.Apple заявляет, что кнопка громкости работает с UIImagePickerController, если вы позволили ей отображать элементы управления камерой.

Другие подходы, такие как прослушивание уведомлений, кажутся неподдерживаемыми взломами, которыми занимается команда Apple.- анекдотично - иногда закрываю глаза на.Чтобы предотвратить появление HUD тома, вы можете использовать недокументированные UIApplication методы:

- (void)setSystemVolumeHUDEnabled:(BOOL)enabled;
- (void)setSystemVolumeHUDEnabled:(BOOL)enabled forAudioCategory:(NSString *)category;

Единственное заявление об их использовании, которое я видел:

UIApplication *app = [UIApplication sharedApplication];
[app setSystemVolumeHUDEnabled:NO forAudioCategory:@"Ringtone"];
[app setSystemVolumeHUDEnabled:NO];

I'mВы не уверены, что вам нужно отключить HUD для определенной категории, а затем вообще, но без надлежащей документации, что трудно понять.

Итак: используйте UIImagePickerController и его кнопки камеры, если хотитебыть в рамках правил.Если вы нашли приложение, которое, кажется, работает вне правил, возможно, оно использует методы, описанные выше.

...