Using AVPlayer and AVPlayerViewController, but audio and video not present - ios

My code looks like this:
_player = [AVPlayer playerWithURL:destination];
_playerVC = [AVPlayerViewController new];
_playerVC.player = _player;
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:_playerVC animated:YES completion:^{
[_player play];
}];
});
_player represents AVPlayer and _playerVC represents AVPlayerViewController. I have strong global references to these objects.
Using terminal, I played the file located at the destination (open -a quicktime\ player destinationURLAbsoluteString) and saw the file is properly loaded since it was playing.
It is a m4v file. I have played a m4a file and it properly gave me audio. I have also substituted the url I have for destination to some remote url and that worked for video. This leads me to believe it has something to do with my video. What's weird is that my AVPlayerViewController does show a black screen with all the normal controls, and even shows the video is 2 minutes and 23 seconds. Upon opening the video file manually, I can see that it is also 2 minutes and 23 seconds.
I can forward through the video properly by dragging the white dot indicative of the video's position, but I never hear anything, nor do I see anything but the black screen and controls.
TL;DR
NSLog(#"Destination: %#",destination);
prints: file:///Users/MyLogin/Library/Developer/CoreSimulator/Devices/694F4C94-F785-4931-A312-4C3E7DE8673A/data/Containers/Data/Application/76C923BE-5B25-41F7-9145-63414657FDF6/Documents/mzvf_5914002519860647075.640x352.h264lc.D2.p.m4v
All in all, it looks like I'm properly retrieving the video, but for some reason my player controller is completely black and void of audio. Any help is much appreciated.
Source Code:
.m file:
#import "ViewController.h"
#import "View2ViewController.h"
#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController ()
#property NSDictionary *requestedSong;
#property (strong) AVPlayer *player; //Declare Globally
#property (strong) AVPlayerViewController *playerVC;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor yellowColor];
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 200, 50)];
button.center = self.view.center;
button.backgroundColor = [UIColor blueColor];
[button setTitle:#"Query Songs" forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonClicked) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:button];
UIButton *button2 = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 200, 50)];
button2.center = CGPointMake(button.center.x, button.center.y + 200);
button2.backgroundColor = [UIColor blueColor];
[button2 setTitle:#"Listen to the first song" forState:UIControlStateNormal];
[button2 addTarget:self action:#selector(button2Clicked) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:button2];
}
-(void)button2Clicked{
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
NSURL *url = [NSURL URLWithString:[_requestedSong objectForKey:#"previewUrl"]];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc]initWithURL:url];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:req];
[task resume];
}
-(void)buttonClicked{
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
NSURL *url = [NSURL URLWithString:#"https://itunes.apple.com/search?media=movie&entity=movie&term=Mad"];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc]initWithURL:url];
NSURLSessionDataTask *task = [session dataTaskWithRequest:req];
[task resume];
}
-(NSURL*)localFilePathForURL:(NSURL *) previewUrl{
//get the directory to use
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) objectAtIndex:0];
//create the full path
NSString *fullPath = [documentsPath stringByAppendingPathComponent:previewUrl.lastPathComponent];
//append the filename and append to document path url
return [NSURL fileURLWithPath:fullPath];
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
NSURL* originalURL = downloadTask.originalRequest.URL;
NSURL *destination = [self localFilePathForURL:originalURL];
NSLog(#"Destination: %#",destination);
NSFileManager *defaultFileManager = [NSFileManager defaultManager];
if([defaultFileManager fileExistsAtPath:destination.absoluteString]){
[defaultFileManager removeItemAtURL:destination error:nil];
}
NSError *error;
#try {
[defaultFileManager copyItemAtURL:location toURL:destination error:&error];
} #catch (NSException *exception) {
NSLog(#"copy caught with exception: %#",exception);
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
_player = [AVPlayer playerWithURL:destination];
_playerVC = [AVPlayerViewController new];
_playerVC.player = _player;
[self presentViewController:_playerVC animated:YES completion:^{
[_player play];
}];
});
NSLog(#"Hello");
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data{
NSError *error2;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:1 error:&error2];
_requestedSong = [[dict valueForKey:#"results"] objectAtIndex:0];
NSLog(#"Searched: %#",[_requestedSong objectForKey:#"trackName"]);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
completionHandler(NSURLSessionResponseAllow);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
.h file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
#end
UPDATE:
Upon using the actual URL endpoint for mad max instead of downloading the video, it also displays a blank video. This must mean there's something weird about the format of the video or how it interacts with the AVPlayer.

You should setup observer for AVPlayer status to call play only when it will be ready to play.
How to do it - check answers here: AVPlayer And Local Files

check the following
if ((_playerVC.player.rate != 0) && (_playerVC.player.error == nil)) {
// player is playing
} else {
// Something wrong
}
also you can observe the rate property of the player. More info here

Related

iOS - NSURLSession not working the second time

I have a UIView that contains a progress bar. What I want to do is simple, I have a button, user clicks that button, app downloads file and show progress in progress bar. I am able to do this when the user clicks the download button the first time. But when the user clicks the second time to download again, NSURLSession delegates are not called.
My UIView .m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self configure];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self configure];
}
return self;
}
-(void)configure
{
[self createSpinner];
[self createProgressBar];
NSArray *URLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
self.docDirectoryURL = [URLs objectAtIndex:0];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:#"com.tinkytickles"];
sessionConfiguration.HTTPMaximumConnectionsPerHost = 1;
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:nil];
}
-(void)createSpinner
{
[self setBackgroundColor:[UIColor colorWithWhite:1.0f alpha:0.5f]];
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self addSubview:spinner];
[spinner setColor:original_new_dark_grey];
[spinner setUserInteractionEnabled:NO];
[spinner setCenter:CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2)];
[spinner setFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[spinner startAnimating];
}
-(void)createProgressBar
{
self.progressBar = [[TYMProgressBarView alloc] initWithFrame:CGRectMake(0, 0, 280, 15)];
[self.progressBar setBarBackgroundColor:[UIColor whiteColor]];
[self.progressBar setBarBorderColor:original_new_dark_grey];
[self.progressBar setBarFillColor:original_new_dark_grey];
[self.progressBar setBarBorderWidth:1.0f];
[self addSubview:self.progressBar];
[self.progressBar setCenter:CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2)];
[self.progressBar setHidden:YES];
self.label = [[UILabel alloc] initWithFrame:CGRectMake(self.progressBar.frame.origin.x, self.progressBar.frame.origin.y - 30, self.progressBar.frame.size.width, 25)];
[self.label setText:NSLocalizedString(locDownloading, nil)];
[self.label setTextAlignment:NSTextAlignmentCenter];
[self.label setTextColor:original_new_dark_grey];
[self.label setFont:quicksand_14];
[self addSubview:self.label];
[self.label setHidden:YES];
}
-(void)showProgressBarWithProgress:(CGFloat)progress withText:(NSString *)text
{
[spinner setHidden:YES];
[self.label setText:[NSString stringWithFormat:NSLocalizedString(locDownloadingAt, nil), text]];
[self.label setHidden:NO];
[self.progressBar setHidden:NO];
[self.progressBar setProgress:progress];
}
-(void)stopAnimating
{
[spinner stopAnimating];
}
-(void)startDownloadingURL:(PromoterDownloadInfo *)downloadInfo
{
info = downloadInfo;
if (!info.isDownloading)
{
if (info.taskIdentifier == -1)
{
info.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:info.downloadSource]];
info.taskIdentifier = info.downloadTask.taskIdentifier;
[info.downloadTask resume];
}
else
{
info.downloadTask = [self.session downloadTaskWithResumeData:info.taskResumeData];
[info.downloadTask resume];
info.taskIdentifier = info.downloadTask.taskIdentifier;
}
}
else
{
[info.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
if (resumeData != nil) {
info.taskResumeData = [[NSData alloc] initWithData:resumeData];
}
}];
}
info.isDownloading = !info.isDownloading;
}
-(void)stopDownload:(PromoterDownloadInfo *)downloadInfo
{
if (!info.isDownloading)
{
if (info.taskIdentifier == -1)
{
info.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:info.downloadSource]];
}
else
{
info.downloadTask = [self.session downloadTaskWithResumeData:info.taskResumeData];
}
info.taskIdentifier = info.downloadTask.taskIdentifier;
[info.downloadTask resume];
info.isDownloading = YES;
}
[self stopAnimating];
[self removeFromSuperview];
}
#pragma mark - NSURLSession Delegate method implementation
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *destinationFilename = downloadTask.originalRequest.URL.lastPathComponent;
NSURL *destinationURL = [self.docDirectoryURL URLByAppendingPathComponent:destinationFilename];
if ([fileManager fileExistsAtPath:[destinationURL path]]) {
[fileManager removeItemAtURL:destinationURL error:nil];
}
BOOL success = [fileManager copyItemAtURL:location
toURL:destinationURL
error:&error];
if (success) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self stopAnimating];
[self removeFromSuperview];
}];
}
else
{
NSLog(#"Unable to copy temp file. Error: %#", [error localizedDescription]);
}
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if (error != nil) {
NSLog(#"Download completed with error: %#", [error localizedDescription]);
}
else{
NSLog(#"Download finished successfully.");
}
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
if (totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown) {
NSLog(#"Unknown transfer size");
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
info.downloadProgress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
[self showProgressBarWithProgress:info.downloadProgress withText:info.fileTitle];
});
}
}
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
// Check if all download tasks have been finished.
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if ([downloadTasks count] == 0) {
if (appDelegate.backgroundTransferCompletionHandler != nil) {
// Copy locally the completion handler.
void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler;
// Make nil the backgroundTransferCompletionHandler.
appDelegate.backgroundTransferCompletionHandler = nil;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Call the completion handler to tell the system that there are no other background transfers.
completionHandler();
// Show a local notification when all downloads are over.
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = NSLocalizedString(locDownloadComplete, nil);
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}];
}
}
}];
}
I use this UIView like this:
PromoterDownloadInfo *info = [[PromoterDownloadInfo alloc] initWithFileTitle:self.title andDownloadSource:#"https://www.mywebsite.com/file.zip"];
PromotersDownloadView *downloadView = [[PromotersDownloadView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.navigationController.view addSubview:downloadView];
[downloadView startDownloadingURL:info];
The first time I clicked the download button it works great. The second time NSURLSession only didCompleteWithError method gets called. Here is what I get from log the second time:
2016-05-12 00:50:47.440 APP[32990:1230071] A background URLSession with identifier com.app already exists!
2016-05-12 00:50:50.614 APP[32990:1230386] Download finished successfully.
What am I doing wrong? I tried to create NSURLSessionConfiguration only once but this way no delegate method gets called. What should I do?
You said:
The first time I clicked the download button it works great. ... Here is what I get from log the second time:
2016-05-12 00:50:47.440 APP[32990:1230071] A background URLSession with identifier com.app already exists!<br />
That error is pointing out that you want to instantiate only one background NSURLSession for a given identifier (and you generally only need/want a single background session). If you were going to instantiate multiple ones, you'd give them unique identifiers, but handling background sessions is complicated enough without unnecessarily having multiple sessions. I'd suggest that you only want a single background session.
You said:
I tried to create NSURLSessionConfiguration only once but this way no delegate method gets called.
Yes, you should have one session configuration. And, just as importantly, only one background session object.
I suspect that there's an issue with your delegate object not being able to keep track of which view it should be updating. Or perhaps you lost reference to your session object and your reference was nil. It could be a couple of different things, and it's hard to know without seeing how you did this.
I'd suggest moving this session configuration code out of the view, and have some shared instance that you can reference anywhere (e.g. a singleton works well, so you can instantiate it from wherever it's first needed, whether from a view or from the app delegate's handleEventsForBackgroundURLSession method).
The only challenge then is how to keep track of which views are keeping track of which network requests. Do you want to have a single view that will keep track of all incomplete requests, regardless of when this view is instantiated? If so, you can use NSNotificationCenter notifications (that way, any view that wants to be notified of progress updates can just observe your custom notification). Or does a given view only care about requests that you initiated from that view?In that case, you might maintain dictionary that maps taskIdentifier values to which view or object needs to know about the status updates (what way you can have your session object keep track of which views care about which tasks). It just depends upon your app's requirements.

passing video url using json in ios

hi I'm trying to view the videos from my server for that i have stored the video url in mysql database
using the json and php code I'm passing the url to the iOS but now I'm getting some problem here
previously using this same format fetching the images from my server but now i want to view the videos this is the first time im working on the videos not to able to get it
this is the code which i used to fetch the url form database and liking to the ios nsurl format
tabecell.m file code:
#import "vediopoliticalCell.h"
#import "vedios.h"
#implementation vediopoliticalCell
//#synthesize movieplayer,titile;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)setDataSource:(vedios *)inVideosObj
{
self.titile.text = inVideosObj.title;
NSURL *url =[NSURL URLWithString:inVideosObj.video];
NSURLRequest *request =[NSURLRequest requestWithURL:url];
connection =[[NSURLConnection alloc] initWithRequest:request delegate:self];
self.responseData = [[NSMutableData alloc]init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
{
[self.responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
MPMoviePlayerController *play = [[MPMoviePlayerController alloc]initWithContentURL:self.responseData];
}
In this code:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
MPMoviePlayerController *play = [[MPMoviePlayerController alloc]initWithContentURL:self.responseData];
}
im getting a waring called:
Incompatible pointer types sending 'NSMutableData ' to parameter of type Nsurl
previously for the image i using this code:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
UIImage *image = [UIImage imageWithData:self.responseData];
self.thumbImageView.image = image;
}
now i dont know how to use for the videos please can anyone help me with this
thanks in advance
self.responseData is NSMutableData but MPMoviePlayerController needs url to load the video.
So, first you have to get url-string from data.
NSString *url =[NSString stringWithUTF8String:[responseData bytes]]
MPMoviePlayerController *play = [[MPMoviePlayerController alloc]initWithContentURL:[NSURL urlWithString:url]];
//Now present the MPMoviePlayerController
Try this
In setDataSource: method
-(void)setDataSource:(vedios *)inVideosObj
{
self.titile.text = inVideosObj.title;
NSURL *url =[NSURL URLWithString:inVideosObj.video];
MPMoviePlayerViewController *videoDeatilView = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
//now you can present this videoDeatilView and
//[videoDeatilView.moviePlayer play]; will play the video
}

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.

AVAudioPlayer not playing my mp3

I'm trying to get a short audio file (mp3) to play in my app. Here is the code i'm using:
AVAudioPlayer *AudioPlayer;
NSError *error;
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"filename"
ofType:#"mp3"]];
AudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
AudioPlayer.delegate = self;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
if (error)
{
NSLog(#"Error: %#",
[error localizedDescription]);
}
else
{
[AudioPlayer play];
}
I don't really know what i'm missing, the examples i've followed seem to match what i'm doing.
edit: I should also mention that the code runs without error, there is a try catch around this.
I had a similar problem due to ARC. Instead of defining the AVAudioPlayer in the same method you are using it, you should should have an instance variable somewhere else, such as the UIViewController. This way ARC doesn't auto release this object and audio can play.
I've made some additions and got it work:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface FirstViewController : UIViewController <AVAudioPlayerDelegate> {
AVAudioPlayer *data;
UIButton *playButton_;
}
#property(nonatomic, retain) IBOutlet UIButton *playButton;
-(IBAction)musicPlayButtonClicked:(id)sender;
#end
#import "ViewController.h"
#implementation FirstViewController
#synthesize playButton=playButton_;
- (IBAction)musicPlayButtonClicked:(id)sender {
NSString *name = [[NSString alloc] initWithFormat:#"09 No Money"];
NSString *source = [[NSBundle mainBundle] pathForResource:name ofType:#"mp3"];
if (data) {
[data stop];
data = nil;
}
data=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: source] error:NULL];
data.delegate = self;
[data play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
In Interface Builder I've added a button and connected it with IBOutlet and musicPlayButtonClicked IBAction.
And don't forget to add AVFoundation framework to your project.
ps
I'm really sorry for my english, please, be indulgent.
I had this problem myself, until I found out that the sound was not coming through the speakers (instead - it was redirected to the calls speaker). Try adding this to redirect the sound through the speakers:
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof (doChangeDefaultRoute),
&doChangeDefaultRoute);

Play MP3 Files with iPhone SDK [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
What's the easiest way to play a music file such as Mp3 with pause button?
very very simple a button play and another button pause that music
These are the codes for the requested actions,
appSoundPlayer is a property of AVAudioPlayer declared in h file. Also this example plays a song in the resource folder.
#pragma mark -
#pragma mark *play*
- (IBAction) playaction {
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"songname" ofType:#"mp3"];
NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
self.soundFileURL = newURL;
[newURL release];
[[AVAudioSession sharedInstance] setDelegate: self];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];
// Registers the audio route change listener callback function
AudioSessionAddPropertyListener (
kAudioSessionProperty_AudioRouteChange,
audioRouteChangeListenerCallback,
self
);
// Activates the audio session.
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];
self.appSoundPlayer = newPlayer;
[newPlayer release];
[appSoundPlayer prepareToPlay];
[appSoundPlayer setVolume: 1.0];
[appSoundPlayer setDelegate: self];
[appSoundPlayer play];
[stopbutton setEnabled:YES];
[playbutton setEnabled: NO];
playbutton.hidden=YES;
pausebutton.hidden =NO;
}//playbutton touch up inside
#pragma mark -
#pragma mark *pause*
-(IBAction)pauseaction {
[appSoundPlayer pause];
pausebutton.hidden = YES;
resumebutton.hidden = NO;
}//pausebutton touch up inside
#pragma mark -
#pragma mark *resume*
-(IBAction)resumeaction{
[appSoundPlayer prepareToPlay];
[appSoundPlayer setVolume:1.0];
[appSoundPlayer setDelegate: self];
[appSoundPlayer play];
playbutton.hidden=YES;
resumebutton.hidden =YES;
pausebutton.hidden = NO;
}//resumebutton touch up inside
#pragma mark -
#pragma mark *stop*
-(IBAction)stopaction{
[appSoundPlayer stop];
[playbutton setEnabled:YES];
[stopbutton setEnabled:NO];
playbutton.hidden=NO;
resumebutton.hidden =YES;
pausebutton.hidden = YES;
}//stopbutton touch up inside
For short sounds or when the MP3 does not play well on the suggested code you can always use:
SystemSoundID soundID;
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/sound.mp3", [[NSBundle mainBundle] resourcePath]]];
AudioServicesCreateSystemSoundID((CFURLRef)url, &soundID);
AudioServicesPlaySystemSound (soundID);
Don't forget to add:
#import <AudioToolbox/AudioToolbox.h>
well here is a good tutorial available.
The theme is
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/audiofile.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = -1;
[audioPlayer play];
and when you want to pause;
[audioPlayer pause];
hope this helps.
I'm afraid the answer stated no longer works in iOS 7 and above. You will need to use the following code:
in the header file (.h)
In order to handle the delegate methods like when the playing of the audio has finished audioPlayerDidFinishPlaying:, inherit from AVAudioPlayerDelegate .
#property (nonatomic, strong) AVAudioPlayer *player;
in the implementation file (.m)
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: resourceName
ofType: #"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
error: nil];
_player = newPlayer;
[_player prepareToPlay];
[_player setDelegate: self];
[_player play];
I like simple code and here is my solution : (Remember to add switch button to get music play. Have fun)
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#interface ViewController ()
{
NSURL* bgURL;
AVAudioPlayer* bgPlayer;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
bgURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"mp3"]];
bgPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:bgURL error:nil];
}
#pragma mark AVAudioPlayer
- (IBAction)toggleMusic:(UISwitch*)sender {
NSLog(#"togging music %s", sender.on ? "on" : "off");
if (bgPlayer) {
if (sender.on) {
[bgPlayer play];
}
else {
[bgPlayer stop];
}
}
}
The Apple documentation here should have everything you need to know.
DIRAC API is free and quite easy to use.
We've used it in my talking robot app http://itunes.apple.com/us/app/daidai/id484833168 and it has been amazing to me how it manages to change the speed and pitch of voice
http://www.dspdimension.com/download/
The oalTouch sample code on the Apple iOS developer web site does what you want, and is ready to run.
It also shows how to test if another app (eg ipod) is playing a file already, which is handy if you want to allow your users to listen to their own music instead of yours.

Resources