iOS監聽耳機插拔的不使用系統通知實現的一種方式

來源:互聯網
上載者:User
前言

目前在iOS中監聽耳機插拔通常使用的方式是利用iOS系統提供的耳機通知事件 AVAudioSessionRouteChangeNotification 來實現。代碼結構如下 系統通知方式

//添加觀察訊息

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:)   name:AVAudioSessionRouteChangeNotification object:nil];

//實現監聽方法

- (void)audioRouteChangeListenerCallback:(NSNotification*)notification {    NSDictionary *interuptionDict = notification.userInfo;    NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];    switch (routeChangeReason) {        case AVAudioSessionRouteChangeReasonNewDeviceAvailable: {//耳機插入            [UIView animateWithDuration:1 animations:^{                self.warningLabel.alpha = 0;            }];        }            break;        case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: {//耳機拔出            [UIView animateWithDuration:1 animations:^{                self.warningLabel.alpha = 1;            }];        }            break;        case AVAudioSessionRouteChangeReasonCategoryChange:            // called at start - also when other audio wants to play            NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");            break;    }}

這個方式的好處是結構清晰,代碼量少。弊端是通知有時候速度比較慢,反應不夠迅速,而且自己不能控制。其實監聽的本質就是發起一個死迴圈,不停的測試耳機孔的狀態。所以可以在自己的程式裡面起一個線程,然後產生一個Runloop,不停的去探測耳機孔的狀態。這種方式在AFNetworking架構裡面也使過。為了不停的偵測網路狀態,AFNetworking就是發起了一個自己的Runloop線程,來監聽網路狀態。 自訂方式

首先定義一個函數,用來判斷耳機孔是否插有耳機。將來在自訂的線程裡面,就是不停的調用這個函數

//判斷耳機孔是否插有耳機- (BOOL)isHeadsetPluggedIn {    AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];    for (AVAudioSessionPortDescription* desc in [route outputs]) {        if ([[desc portType] isEqualToString:AVAudioSessionPortHeadphones])            return YES;    }    return NO;}

定義一個靜態變數,用來儲存RunLoop對象。定義為靜態變數,就不要考慮這個變數的生命週期了。

static NSRunLoop *_HeadsetRunLoop;

定義偵測耳機的線程

- (NSThread *)startHeadsetThread {    static NSThread *_HeadsetThread = nil;    static dispatch_once_t oncePredicate;    dispatch_once(&oncePredicate, ^{        _HeadsetThread  =        [[NSThread alloc] initWithTarget:self                                selector:@selector(HeadsetThreadEntryPoint:)                                  object:nil];        [_HeadsetThread  start];    });    return _HeadsetThread;}

// 產生一個一直啟動並執行RunLoop

- (void)HeadsetThreadEntryPoint:(id)__unused object {    @autoreleasepool {        [[NSThread currentThread] setName:@"com.olami.infraredTV"];        _HeadsetRunLoop = [NSRunLoop currentRunLoop];        [_HeadsetRunLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];        [_HeadsetRunLoop run];    }}

在這裡使用NSMachPort來作為RunLoop的輸入源,但是這個輸入源什麼也不做,作用就是讓RunLoop一直活著,不會執行一次就退出。這個函數是整個方法實現的核心代碼。

//利用自訂的線程偵測耳機

//利用自訂的線程偵測耳機- (void)startDetectHeadset {    if (_HeadsetRunLoop) {        [self.timer invalidate];        _timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(detectHeadset) userInfo:nil repeats:YES];        [_HeadsetRunLoop addTimer:_timer forMode:NSRunLoopCommonModes];    }else{        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{            if (_HeadsetRunLoop) {                [self.timer invalidate];                _timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(detectHeadset) userInfo:nil repeats:YES];                [_HeadsetRunLoop addTimer:_timer forMode:NSRunLoopCommonModes];            }        });    }}

在這裡使用了一個定時器來監聽耳機孔的插拔狀態。如果想更迅速,可以使用CADisplayLink來實現。
把定時器的RunLoop設定為自訂的就行了

//耳機偵測回呼函數

- (void)detectHeadset {    if ([self isHeadsetPluggedIn]) {        NSLog(@"耳機已經插入");    }else{        NSLog(@"耳機已經拔出");    }}

當然了,這樣實現還是把輪子造了一邊。但是起碼給了一個思路,當自己的APP需要監聽一些裝置或者變數的狀態的時候。可以使用這種方法來實現。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.