I have audio player. I download audio in this way
- (void) song{
if (_index == 0) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"1.mp3"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:NO];
if (!fileExists) {
NSString *stringURL = #"https://drive.google.com/uc?export=download&id=0B6zMam2kAK39VHZ1cUZsM3BhQXM";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
[urlData writeToFile:filePath atomically:YES];
}
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:filePath] error:nil];
}
}
But when audio downloading I can’t do anything. User interface stop.
How can download audio and do anything in user interface simultaneously?
Give your method a block to execute when finished, then run the download code in the background. Lets say, for your case the output is a local file with the downloaded content:
- (void)songWithCompletion:(void (^)(NSString *))completion {
NSString *filePath = [self song];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(filePath);
});
}
Change the song method to return filePath. Don't ever call it directly, only via songWithCompletion.
- (void)song {
// ... your code from the OP
// don't allocate the audio player here, just return the local file
return filePath;
}
Call it like this...
[self songWithCompletion:^(NSString *filePath) {
if (filePath) {
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:filePath] error:nil];
// you should really handle audio player error here, too
} else {
// handle error
}
}];
You are downloading the file in the main thread. you need to make an asynchronous call in order to avoid stopping UI.
-(void)downloadAudio
{
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"https://drive.google.com/uc?export=download&id=0B6zMam2kAK39VHZ1cUZsM3BhQXM"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
receivedData = [NSMutableData data] ;
} else {NSLog(#"no connection!");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSLog(#"Succeed! Received %d bytes of data",[receivedData length]);
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//NSLog(#"%#", [documentPaths objectAtIndex:0]);
NSString *documentDirectoryPath = [documentPaths objectAtIndex:0];
NSString *folderPath = [documentDirectoryPath stringByAppendingPathComponent:#"audioFile.mp3"];
[receivedData writeToFile:folderPath atomically:YES];
NSURL *soundURL = [NSURL fileURLWithPath:folderPath];
NSError *error;
if ([[NSFileManager defaultManager] fileExistsAtPath:folderPath]) {
player = [[AVAudioPlayer alloc]initWithContentsOfURL:soundURL error:&error];
player.volume=0.5;
NSError *error = nil;
if (!error) {
[player play];
NSLog(#"File is playing!");
}
else{
NSLog(#"Error in creating audio player:%#",[error description]);
}
}
else{
NSLog(#"File doesn't exist");
}
}
Related
I want to download or save youtube video in document directory and then play that video using MPMoviePlayerViewController. But I don't know why my code is not working.
I'm using this below code :
prgrma mark- download Or save
-(IBAction)onclick_download:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"Downloading Started");
NSString *urlToDownload = #"youtubeurl";
NSURL *url = [NSURL URLWithString:urlToDownload];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"thefile.mp4"];
//saving is done on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[urlData writeToFile:filePath atomically:YES];
NSLog(#"File Saved !");
});
}
});
}
pragma mark- Play video from document directory
-(IBAction)onclick_playvideolocally:(id)sender
{
[self playvideolocally];
}
-(void)playvideolocally
{
NSURL *videoUrl;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
NSLog(#"files array %#", filePathsArray);
NSString *fullpath;
for ( NSString *apath in filePathsArray )
{
fullpath = [documentsDirectory stringByAppendingPathComponent:apath];
videoUrl =[NSURL fileURLWithPath:fullpath];
}
MPMoviePlayerViewController *videoPlayerView = [[MPMoviePlayerViewController alloc] initWithContentURL:videoUrl];
[self presentMoviePlayerViewControllerAnimated:videoPlayerView];
[videoPlayerView.moviePlayer play];
}
As your link you provided in url is for youtube so it is not downloaded or saved in local
Use this for youtube
Ive used classes from this project: https://github.com/larcus94/LBYouTubeView It works fine for me. I can download youtube videos.
LBYouTubeExtractor *extractor = [[[LBYouTubeExtractor alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:(#"http://www.youtube.com/watch?v=%#"), self.videoID ]] quality:LBYouTubeVideoQualityLarge] autorelease];
[extractor extractVideoURLWithCompletionBlock:^(NSURL *videoURL, NSError *error) {
if(!error) {
NSLog(#"Did extract video URL using completion block: %#", videoURL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL: videoURL];
NSString *pathToDocs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filename = [NSString stringWithFormat:(#"video_%#.mp4"), self.videoID ];
[data writeToFile:[pathTODocs stringByAppendingPathComponent:filename] atomically:YES];
NSLog(#"File %# successfully saved", filename);
});
} else {
NSLog(#"Failed extracting video URL using block due to error:%#", error);
}
}];
i'm trying to design audio streaming app everything is working, but i don't know how to download audio file to the device and read it afterword.
Download audio to document directory.
play it back from document directory.
Added code:
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [path firstObject];
NSString *filePath = [documentDirectory stringByAppendingPathComponent:#"evet.mp3"];
// UIImage *cellImage = [[UIImage alloc] initWithContentsOfFile:filePath];
NSLog(#"%#",filePath);
NSError *error;
NSData *_objectData = [NSData dataWithContentsOfURL:[NSURL URLWithString:filePath]];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:_objectData error:&error];
[audioPlayer play];
Based on the code you posted try this.
Change
NSData *_objectData = [NSData dataWithContentsOfURL:[NSURL URLWithString:filePath]];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:_objectData error:&error];
to this:
NSURL *fileURL = [NSURL fileURLWithPath:filePath isDirectory:NO];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
AVAudioPlayer wants a URL object (which needs to be a local URL not a remote web address, hence fileURLWithPath:) not the data itself.
You were trying to give the NSData itself to the audio player.
Fetch your audio file in document directory
- (NSString *)getCacheDirectoryPathForAudio:(NSString *)filePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it
NSString *documentsDirectory = [paths objectAtIndex:0]; //create NSString object, that holds our exact path to the documents directory
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mp3", filePath]]; //add
return fullPath;
}
Initiate player with file path
NSString *pathToSaveAudioString = [self getCacheDirectoryPathForAudio:#“filename”];
NSURL* url = [NSURL fileURLWithPath:pathToSaveAudioString];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:pathToSaveAudioString];
if (fileExists) {
NSError* error = nil;
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[self.player setDelegate:self];
if(!self.player)
{
NSLog(#"Error creating player: %#", error);
}
}
else
{
NSLog(#“File Not Exist: %#");
}
and play it using
[self.player play];
Use Delegate methods to check status
#pragma mark - AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
}
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
}
For more details follow
http://iosdeveloperzone.com/2012/10/01/tutorial-playing-audio-with-avaudioplayer/
I have simple code
NSData *D = [self FindDatafromDocument:#"ASDF"];
player = [[AVAudioPlayer alloc] initWithData:D error:nil];
[player setDelegate:self];
[player play];
Method
- (NSData *)FindDatafromDocument:(NSString *)Name {
NSData *IMG;
NSError *error;
NSArray *directoryContents = [[NSArray alloc] init];
directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[Utility getDocumentDirectory] error:&error];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",Name];
NSArray *ArrImages = [directoryContents filteredArrayUsingPredicate:predicate];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *Doc = [paths objectAtIndex:0];
for (NSString *imageName in ArrImages) {
if ([imageName rangeOfString:#".caf"].location != NSNotFound) {
IMG = [[NSFileManager defaultManager] contentsAtPath:[NSString stringWithFormat:#"%#/%#",Doc,imageName]];
}
}
return IMG;
}
I want to create an application that automatically downloads a folder from my own server and store it locally on the iPad/iPhone. How can i accomplish this and where does the folder get stored on the local iDevice ? Therefore how will i access it afterwards? Many thanks for your help
The best way to do so was actually putting all the pictures for example in one zip file, downloading it and unzipping it on the real device using this code :
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSURL *url = [NSURL URLWithString:#"someDirectory/newPics.zip"];
NSError *error = nil;
// 2
NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error];
if(!error)
{
// 3
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *zipPath = [path stringByAppendingPathComponent:#"newPics.zip"];
[data writeToFile:zipPath options:0 error:&error];
if(!error)
{
ZipArchive *za = [[ZipArchive alloc] init];
// 1
if ([za UnzipOpenFile: zipPath]) {
// 2
BOOL ret = [za UnzipFileTo: path overWrite: YES];
if (NO == ret){} [za UnzipCloseFile];
// 3
NSString *imageFilePath = [path stringByAppendingPathComponent:#"newPics/pic1.png"];
//[self removeImage:zipPath];
[[NSFileManager defaultManager] removeItemAtPath:zipPath error: &error];
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *fileURL = [NSURL fileURLWithPath:imageFilePath];
[_webV loadRequest:[NSURLRequest requestWithURL:fileURL]];
});
}
}
else
{
NSLog(#"Error saving file %#",error);
}
}
else
{
NSLog(#"Error downloading zip file: %#", error);
}
});
It's the best way to do it , fast and reliable.
I'm trying to stream an radio in my app.
I'm using AVAudioPlayer, but I have an error I don't understand :
NSString *urlString = #"http://broadcast.infomaniak.net/radionova-high.mp3";
NSURL *myURL = [NSURL URLWithString:urlString];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:myURL error:&error];
if (self.audioPlayer == nil){
NSLog(#"Error loading clip: %#", [error localizedDescription]);
}
else {
self.audioPlayer.delegate = self;
self.audioPlayer.volume = 0.5;
[self.audioPlayer play];
}
And I have the following error :
Error loading clip: The operation couldn’t be completed. (OSStatus error -43.)
Does anyone see what's wrong ?
EDIT :
This is what the Apple docs say:
The AVAudioPlayer class does not provide support for streaming audio
based on HTTP URL's. The URL used with initWithContentsOfURL: must be
a File URL (file://). That is, a local path.
Now what ? :(
download file to document directoty then play file
NSString *urlString = #"http://broadcast.infomaniak.net/radionova-high.mp3";
NSURL *myURL = [NSURL URLWithString:urlString];
NSData *audioData = [NSData dataWithContentsOfURL:myURL];
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#.mp3", docDirPath , fileName];
[audioData writeToFile:filePath atomically:YES];
NSError *error;
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
if (self.audioPlayer == nil) {
NSLog(#"AudioPlayer did not load properly: %#", [error description]);
} else {
self.audioPlayer.delegate = self;
self.audioPlayer.volume = 0.5;
[self.audioPlayer play];
}
I have a UITableView displaying a llist f files in the Documents Directory... and I want it to play the audio file in the Documents directory when pressed...
It runs with no errores but doesn't play the audio when pressed...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.caf",indexPath.row+1]];
NSURL *audioURL = [NSURL URLWithString:fileName];
NSData *audioData = [NSData dataWithContentsOfURL:audioURL];
NSError *error;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
_audioPlayer.delegate = self;
[_audioPlayer play];
}
Change this line:
NSURL *audioURL = [NSURL URLWithString:fileName];
to this:
NSURL *audioURL = [NSURL fileURLWithPath:fileName isDirectory:NO];
And then just do:
if(_audioPlayer == nil)
{
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
}
else
{
_audioPlayer = [self.audioAlert initWithContentsOfURL:audioURL error:nil];
}
To start out, the best way to declare a files path is this
- (NSString *)docsdir {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
}
in your header, declareNSString *Path;
then, declare the path like this when the view loads
Path = [[self docsdir]stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.caf",indexPath.row+1]];
if (![[NSFileManager defaultManager]fileExistsAtPath:Path]) {
[[NSFileManager defaultManager]copyItemAtPath:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"%d",indexPath.row+1] ofType:#"caf"] toPath:Path error:nil];
}
now to play it, do this
AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:Path] error:&error];
player.delegate = self;
[player play];