Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unable to play music from document directory through AVPlayer in iOS?

I am picking the music file using MediaPickerController.After i pick the music file from the picker then i save the file to document directory.

Following is code for picking & saving to document directory

//code to click on music button
- (IBAction)addMusic:(id)sender
{
    MPMediaPickerController *soundPicker=[[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
    soundPicker.delegate=self;
    soundPicker.allowsPickingMultipleItems=NO;
    [self presentViewController:soundPicker animated:YES completion:nil];
}

- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
    NSLog(@"music files delegate called");
    MPMediaItem *item = [[mediaItemCollection items] objectAtIndex:0];
    [self uploadMusicFile:item];
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void) uploadMusicFile:(MPMediaItem *)song
{
    NSURL *url = [song valueForProperty: MPMediaItemPropertyAssetURL];

    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
                                                                      presetName:AVAssetExportPresetAppleM4A];

    exporter.outputFileType =   @"com.apple.m4a-audio";

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * myDocumentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

    [[NSDate date] timeIntervalSince1970];
    NSTimeInterval seconds = [[NSDate date] timeIntervalSince1970];
    NSString *intervalSeconds = [NSString stringWithFormat:@"%0.0f",seconds];

    NSString * fileName = [NSString stringWithFormat:@"%@.mp4",intervalSeconds];

    NSString *exportFile = [myDocumentsDirectory stringByAppendingPathComponent:fileName];

    NSURL *exportURL = [NSURL fileURLWithPath:exportFile];
    exporter.outputURL = exportURL;

    // do the export
    // (completion handler block omitted)
    [exporter exportAsynchronouslyWithCompletionHandler:
     ^{
         int exportStatus = exporter.status;

         switch (exportStatus)
         {
             case AVAssetExportSessionStatusFailed:
             {
                 NSError *exportError = exporter.error;
                 NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
                 break;
             }
             case AVAssetExportSessionStatusCompleted:
             {
                 NSLog (@"AVAssetExportSessionStatusCompleted");
                 //music data is NSdata
                 music_data = [NSData dataWithContentsOfFile: [myDocumentsDirectory
                                                               stringByAppendingPathComponent:fileName]];

                 // NSLog(@"Data %@",data);
                 // data = nil;

                 break;
             }
             case AVAssetExportSessionStatusUnknown:
             {
                 NSLog (@"AVAssetExportSessionStatusUnknown"); break;
             }
             case AVAssetExportSessionStatusExporting:
             {
                 NSLog (@"AVAssetExportSessionStatusExporting"); break;
             }
             case AVAssetExportSessionStatusCancelled:
             {
                 NSLog (@"AVAssetExportSessionStatusCancelled"); break;
             }
             case AVAssetExportSessionStatusWaiting:
             {
                 NSLog (@"AVAssetExportSessionStatusWaiting"); break;
             }
             default:
             {
                 NSLog (@"didn't get export status"); break;
             }
         }
     }];
}

Code to play the music file from document directory

- (void)musicPlay:(UIGestureRecognizer *)recognizer
{
    if(!isMusicPlaying)
    {
        if([musicFile isEqualToString:@"none"])
        {
            NSLog(@"INSIDE IF");

            UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Warning" message:@"No music exist" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];

            [alert show];
        }
        else
        {
            NSURL *fileURL;
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectory = [paths objectAtIndex:0];
            bc.music_upload=[bc.music_upload lastPathComponent];
            NSLog(@"music uplaod is %@",bc.music_upload);
            NSString* path = [documentsDirectory stringByAppendingPathComponent:bc.music_upload];
            BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
            if(fileExists)
            {
                NSLog(@"file already exist");
                fileURL = [NSURL fileURLWithPath:path];
                NSLog(@"file url is %@",fileURL);
            }
            else
            {
                NSLog(@"file already not exist");
                if(![musicFile containsString:@"http://"])
                {
                    musicFile=[IMAGE_BASE_URL stringByAppendingString:musicFile];

                }
                fileURL = [NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:musicFile]];
            }

            NSLog(@"file url is %@",fileURL);
            isMusicPlaying=true;
            [self.img_music setImage:[UIImage imageNamed:@"play_stop.png"]];
            playerItem = [AVPlayerItem playerItemWithURL:fileURL];
            player = [AVPlayer playerWithPlayerItem:playerItem];
            //player = [AVPlayer playerWithURL:path];
            [player play];
        }
    }
    else
    {
        isMusicPlaying=false;
        [player pause];
        [self.img_music setImage:[UIImage imageNamed:@"music-icon.png"]];
    }
}

I am able to save the file & when i check if file exists in document directory then i am able to find the file.But i am not able to play the file.I didn't understand what is the problem.Is problem with the music file or with my music player code? ' EDIT: I have tried this code but it is making app hang & unresponsive.

NSURL *url = [NSURL URLWithString:@"http://sound18.mp3pk.com/pop_remix/ebodf11/ebodf11-15(www.songs.pk).mp3"];

NSData *data = [NSData dataWithContentsOfURL:url];

AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];

[audioPlayer play];

EDIT:

I think the issue is with the conversion of the MPMediaItem into NSdata.Because when i convert the MPMediaItem to NSData then i am able to send it server & it is played on the browser.But i try to play with AVPlayer then i face this issue?

like image 476
TechChain Avatar asked Sep 15 '15 04:09

TechChain


1 Answers

From Apple article

As with assets and items, initializing the player does not mean it’s ready for playback. You should observe the player’s status property, which changes to AVPlayerStatusReadyToPlay when it is ready to play. You can also observe the currentItem property to access the player item created for the stream.

Add the observer to your player

- (void)musicPlay:(UIGestureRecognizer *)recognizer {
    // your player code
    [player addObserver:self forKeyPath:@"status" options:0 context:nil];
}

// Observe for the player status
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {


    if (object == _player && [keyPath isEqualToString:@"status"]) {
        if (_player.status == AVPlayerStatusFailed) {
            NSLog(@"AVPlayer Failed");

        } else if (_player.status == AVPlayerStatusReadyToPlay) {
            NSLog(@"AVPlayerStatusReadyToPlay");
            [_player play];


        } else if (_player.status == AVPlayerItemStatusUnknown) {
            NSLog(@"AVPlayer Unknown");

        }
    }
}
like image 161
arthankamal Avatar answered Nov 15 '22 03:11

arthankamal