Search code examples
iosavaudioplayeraccelerometer

Need help using Accelerometer in iOS


I am working on an app that would play a beep for each position the user holds their iOS device (standing, lying on its front/back, or on its side). At the moment, I am able to play a sound when the user has the device on its side, however, the problem is that because I have the accelerometer values linked with the slider, the beeping sound is continuous (i.e. it plays the sound as long as the user is holding the device on its side), rather than just once.

I would like the user to simply hold the device steady on its side, and then a single beep sound is made, allowing the user to then hold the device in the other positions in turn, and wait for another beep sound. I want the user to go step by step by step and hold the device in each position one at a time, moving on to the next position only after hearing a beep.

Here is the code that I am working with:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{

    NSLog(@"(%.02f, %.02f, %.02f)", acceleration.x, acceleration.y, acceleration.z);
    slider.value = acceleration.x;

    if (slider.value == -1)
        [self pushBeep];

    else if (slider.value == 0.00)
        [self pushBap];

    else if (slider.value == 1)
        [self pushBop];

...

and here is the code for my pushBeep() method (FYI, the methods pushBeep/pushBap/pushBop are all identical):

-(void) pushBeep {

    NSString *soundPath =[[NSBundle mainBundle] pathForResource:@"beep-7" ofType:@"wav"];
    NSURL *soundURL = [NSURL fileURLWithPath:soundPath];

    NSError *ierror = nil;
    iPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&ierror];

    [iPlayer play];
}

Can anyone figure out what is the problem here?


Solution

  • I think instead of manually polling the accelerometer you should use the built in Orientation Notifications. You could use something like the below if you needed FaceUp and FaceDown orientations. Or you can use the second method for simply landscape, portrait.

    First Method that relies on the device orientation. Important if you need FaceUp or FaceDown orientations or if you don't have a UIViewController.

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter]
       addObserver:self selector:@selector(orientationChanged:)
       name:UIDeviceOrientationDidChangeNotification
       object:[UIDevice currentDevice]];
    

    And here is the method to build.

    - (void) orientationChanged:(NSNotification *)note
    {
       UIDevice * device = note.object;
       switch(device.orientation)
       {
           case UIDeviceOrientationPortrait:
           /* Play a sound */
           break;
    
           case UIDeviceOrientationPortraitUpsideDown:
           /* Play a sound */
           break;
    
           // ....
    
           default:
           break;
       };
    }
    

    Second Method that relies on interfaceOrientations of a UIViewController.

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        switch (toInterfaceOrientation) {
            case UIInterfaceOrientationLandscapeLeft:
                /* Play a Sound */
                break;
    
            case UIInterfaceOrientationPortrait:
                /* Play a Sound */
                break;
    
                // .... More Orientations
    
            default:
                break;
        }
    }