简体   繁体   中英

AVAudioPlayer doesn't play mp3?

I want my AVAudioPlayer to play some mp3 files. It plays some of them but I have one file that can't be played!

To play the file I download it on my device into application folder and init it this way:

[[AVAudioPlayer alloc] initWithContentsOfURL:soundPath error:nil];

How to play the file? Why it doesn't play?

Link to a file: abc.mp3

EDIT:

(Here is the code that shows the error. There is a README inside the code. Try on the device.)

***.pch

#import <Availability.h>

#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <SystemConfiguration/SystemConfiguration.h>
    #import <MobileCoreServices/MobileCoreServices.h>
    #import <AVFoundation/AVFoundation.h>
    #import <AudioToolbox/AudioToolbox.h>
#endif



ViewController.h

#import <UIKit/UIKit.h>
#import "AFNetworking.h"

@interface SCRViewController : UIViewController <AVAudioPlayerDelegate>
{
    UIButton *button;
    __block UIProgressView *view;
    NSOperationQueue *queue;
    __block BOOL isFile;
    UIButton *play;
    NSString *path;
    AVAudioPlayer *_player;
}

@end


ViewController.m

#import "ViewController.h"

@implementation SCRViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setBackgroundColor:[UIColor yellowColor]];
    [button setFrame:CGRectMake(50, 50, 220, 50)];
    [button addTarget:self action:@selector(download) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Download" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
    [self.view addSubview:button];

    play = [UIButton buttonWithType:UIButtonTypeCustom];
    [play setBackgroundColor:[UIColor yellowColor]];
    [play setFrame:CGRectMake(50, 150, 220, 50)];
    [play addTarget:self action:@selector(play) forControlEvents:UIControlEventTouchUpInside];
    [play setTitle:@"Play" forState:UIControlStateNormal];
    [play setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [play setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
    [self.view addSubview:play];

    self->view = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
    self->view.frame = CGRectMake(10, 120, 300, 20);
    [self->view setProgress:0];
    [self.view addSubview:self->view];

    queue = [[NSOperationQueue alloc] init];

    isFile = NO;
}

- (void) download
{
    [button setBackgroundColor:[UIColor brownColor]];
    [button setTitleColor:[UIColor whiteColor] forState:UIControlStateDisabled];
    [button setEnabled:NO];

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://iwheelbuy.com/abc.mp3"]];

    //-------------------------------------------------------
    //-------------------------------------------------------
    // READ ME
    //-------------------------------------------------------
    //-------------------------------------------------------
    // Test in on device
    // I have uploaded another song for you. You can change link to http://iwheelbuy.com/def.mp3 and check the result
    // def.mp3 works fine on the device
    //-------------------------------------------------------
    //-------------------------------------------------------

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    path = [path stringByAppendingPathComponent:@"song"];

    if ( [[NSFileManager defaultManager] fileExistsAtPath:path])
        [[NSFileManager defaultManager] removeItemAtPath:path error:nil];

    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
     {
         isFile = YES;
     } failure:^(AFHTTPRequestOperation *operation, NSError *error)
     {
         //
     }];
    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
     {
         CGFloat done = (CGFloat)((int)totalBytesRead);
         CGFloat expected = (CGFloat)((int)totalBytesExpectedToRead);
         CGFloat progress = done / expected;
         self->view.progress = progress;
     }];
    [queue addOperation:operation];
}

- (void) play
{
    if (isFile)
    {
        NSError *error = nil;
        NSURL *url = [NSURL fileURLWithPath:path];
        _player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
        if(error || !_player)
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:[error description] delegate:nil cancelButtonTitle:@"Try def.mp3" otherButtonTitles:nil];
            [alert show];
        }
        else
        {
            [_player play]; // plays fine
            [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
            [[AVAudioSession sharedInstance] setActive: YES error: nil];
        }
    }
    else
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Warning" message:@"Download the file plz" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
        [alert show];
    }
}

@end

Non-ARC

You have to retain it during playback because it does not retain itself. It will stop playing instantly once it is dealloc-ed.

ARC

You need to hold the AVAudioPlayer instance in the class. And release it after it stops playing. For example,

#import <AVFoundation/AVFoundation.h>

@interface TAViewController () <AVAudioPlayerDelegate> {
    AVAudioPlayer *_somePlayer;   // strong reference
}
@end

@implementation TAViewController

- (IBAction)playAudio:(id)sender
{
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"kogmawjoke" withExtension:@"mp3"];
    _somePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:NULL];
    _somePlayer.delegate = self;
    [_somePlayer play];
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    if (player == _somePlayer) {
        _somePlayer = nil;
    }
}

@end
http://bugreport.apple.com

Engineering has determined that this issue behaves as intended based on the following information:

Could repro with attached sample app, but this is an expected behavior from AudioFile.

The issue is that AVAudioPlayer is being initialized with a url without a file extension and the corresponding file does not have a valid ID3 tag.Without a file extension or valid data, we cannot determine the right file format and hence such files will fail to open.This is an expected behavior.

In the sample code attached:

path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

path = [path stringByAppendingPathComponent:@"song"];

--> path will be something like:

/var/mobile/Applications/2FFD0147-E56B-47D4-B143-A9F19BE92818/Documents/song

--> NOTE: no file extension at the end.

abc.mp3 has an invalid ID3 tag size (0x2EE) unlike def.mp3 which has a valid tag size (0x927). Hence when these are specified as "…./song" without any extension, AudioFile just looks at the data and finds a valid sync word for def.mp3 but not for abc.mp3.

However, replacing stringByAppendingPathComponent:@"song" with stringByAppendingPathComponent:@"song.mp3" succeeds for abc.mp3, and could help for other mp3 files in general.

We consider this issue closed. If you have any questions or concern regarding this issue, please update your report directly ( http://bugreport.apple.com ).

Thank you for taking the time to notify us of this issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM