Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically detect earpiece in iphone?

I'm currently working on a project that involves playing music from the iphone music library within the app inside. I'm using MPMediaPickerController to allow the user to select their music and play it using the iPod music player within the iPhone.

However, i ran into problem when the user insert his earpiece and removes it. The music will suddenly stop playing for no reason. After some testing, i found out that the iPod player will pause playing when the user unplug his earpiece from the device. So is there any way to programatically detect if the earpiece has been unplug so that i can resume playing the music? Or is there any way to prevent iPod player from pausing when the user unplug his earpiece?

like image 380
Cheng Lai Avatar asked Dec 02 '09 10:12

Cheng Lai


People also ask

How to improve iPhone earphone sound quality?

Go to Settings > Accessibility > Audio/Visual > Headphone Accommodations. Tap Custom Audio Setup. Follow the instructions on your screen. When finished, tap Use Custom Settings to apply the custom settings suggested based on your choices.

How to adjust volume for earbuds on iPhone?

Go to Settings , then tap Sounds & Haptics (iPhone 7 and later) or Sounds (earlier models). Tap Headphone Safety. Turn on Reduce Loud Sounds, then drag the slider. iPhone analyzes your headphone audio and reduces any sound above the level you set.


3 Answers

You should register for AudioRoute changed notification and implement how you want to handle the rout changes

    // Registers the audio route change listener callback function
    AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange,
                                     audioRouteChangeListenerCallback,
                                     self);

and within the callback, you can get the reason for route change

  CFDictionaryRef   routeChangeDictionary = inPropertyValue;

  CFNumberRef routeChangeReasonRef =
  CFDictionaryGetValue (routeChangeDictionary,
            CFSTR (kAudioSession_AudioRouteChangeKey_Reason));

  SInt32 routeChangeReason;

      CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);

  if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) 
  {
       // Headset is unplugged..

  }
  if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable)
  {
       // Headset is plugged in..                   
  }
like image 60
prakash Avatar answered Oct 21 '22 07:10

prakash


If you just want to check whether headphones are plugged in at any given time, without listening to route changes, you can simply do the following:

OSStatus error = AudioSessionInitialize(NULL, NULL, NULL, NULL);
if (error) 
    NSLog("Error %d while initializing session", error);

UInt32 routeSize = sizeof (CFStringRef);
CFStringRef route;

error = AudioSessionGetProperty (kAudioSessionProperty_AudioRoute,
                                 &routeSize,
                                 &route);

if (error) 
    NSLog("Error %d while retrieving audio property", error);
else if (route == NULL) {
    NSLog(@"Silent switch is currently on");
} else  if([route isEqual:@"Headset"]) {
    NSLog(@"Using headphones");
} else {
    NSLog(@"Using %@", route);
}

Cheers, Raffaello Colasante

like image 20
Raffaello Colasante Avatar answered Oct 21 '22 08:10

Raffaello Colasante


I see you are using the MPMediaPlayer Framework however the microphone handling is done using the AVAudioPlayer framework, which you will need to add to your project.

Apple's website has code from the AVAudioPlayer framework which I use to handle interruptions from a user plugging in or removing the Apple microphone headphones.

Check out Apple's iPhone Dev Center Audio Session Programming Guide.

- (void) beginInterruption {
    if (playing) {
        playing = NO;
        interruptedWhilePlaying = YES;
        [self updateUserInterface];
    }
}

NSError *activationError = nil;
- (void) endInterruption {
    if (interruptedWhilePlaying) {
        [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
        [player play];
        playing = YES;
        interruptedWhilePlaying = NO;
        [self updateUserInterface];
    }
}

My code is a little different and some of this may help you:

    void interruptionListenerCallback (
                                   void *inUserData,
                                   UInt32   interruptionState
) {
    // This callback, being outside the implementation block, needs a reference
    //  to the AudioViewController object
    RecordingListViewController *controller = (RecordingListViewController *) inUserData;

    if (interruptionState == kAudioSessionBeginInterruption) {

        //NSLog (@"Interrupted. Stopping playback or recording.");

        if (controller.audioRecorder) {
            // if currently recording, stop
            [controller recordOrStop: (id) controller];
        } else if (controller.audioPlayer) {
            // if currently playing, pause
            [controller pausePlayback];
            controller.interruptedOnPlayback = YES;
        }

    } else if ((interruptionState == kAudioSessionEndInterruption) && controller.interruptedOnPlayback) {
        // if the interruption was removed, and the app had been playing, resume playback
        [controller resumePlayback];
        controller.interruptedOnPlayback = NO;
    }
}

void recordingListViewMicrophoneListener (
                         void                      *inUserData,
                         AudioSessionPropertyID    inPropertyID,
                         UInt32                    inPropertyValueSize,
                         const void                *isMicConnected
                         ) {

    // ensure that this callback was invoked for a change to microphone connection
    if (inPropertyID != kAudioSessionProperty_AudioInputAvailable) {
        return;
    }

    RecordingListViewController *controller = (RecordingListViewController *) inUserData;

    // kAudioSessionProperty_AudioInputAvailable is a UInt32 (see Apple Audio Session Services Reference documentation)
    // to read isMicConnected, convert the const void pointer to a UInt32 pointer
    // then dereference the memory address contained in that pointer
    UInt32 connected = * (UInt32 *) isMicConnected;

    if (connected){
        [controller setMicrophoneConnected : YES];
    }
    else{
        [controller setMicrophoneConnected: NO];    
    }

    // check to see if microphone disconnected while recording
    // cancel the recording if it was
    if(controller.isRecording && !connected){
        [controller cancelDueToMicrophoneError];
    }
}
like image 2
Brock Woolf Avatar answered Oct 21 '22 08:10

Brock Woolf