2012-03-06 17 views
17

Sto costruendo un lettore MP3 per iOS che riproduce file audio ospitati sul web. Voglio offrire la possibilità di riprodurre i file offline, così ho il download dei file usando ASIHTTP ma non riesco a trovare informazioni su initlzing AVPlayer con un mp3 nella directory dei documenti dell'app. Qualcuno l'ha già fatto prima? È possibile?File AVPlayer e file locali

* Ho inviato una risposta qui sotto che mostra come utilizzare AvPlayer per iOS per file locali e http. Spero che questo ti aiuti!

+0

Hai pensato di usare lo SQLite interna al posto dei documenti dir? – rwyland

risposta

31

ho deciso di rispondere alla mia domanda, perché mi sentivo come ci sia molta documentazione su come utilizzare l'Apple fornito AVPlayer sia per i file locali e lo streaming (su HTTP). Per aiutare a capire la soluzione, ho messo insieme un sample project on GitHub in Objective-C e il Swift Il codice sotto è Objective-C ma puoi scaricare il mio esempio Swift per vederlo. È molto simile!

Quello che ho trovato è che i due modi di configurare i file sono quasi identici, tranne per il modo in cui istanziate il tuo NSURL per la catena Asset> PlayerItem> AVPlayer.

Ecco una descrizione dei metodi di base

file h (codice parziale)

-(IBAction) BtnGoClick:(id)sender; 
-(IBAction) BtnGoLocalClick:(id)sender; 
-(IBAction) BtnPlay:(id)sender; 
-(IBAction) BtnPause:(id)sender; 
-(void) setupAVPlayerForURL: (NSURL*) url; 

di file .m (codice parziale)

-(IBAction) BtnGoClick:(id)sender { 

    NSURL *url = [[NSURL alloc] initWithString:@""]; 

    [self setupAVPlayerForURL:url]; 
} 

-(IBAction) BtnGoLocalClick:(id)sender { 

    // - - - Pull media from documents folder 

    //NSString* saveFileName = @"MyAudio.mp3"; 
    //NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    //NSString *documentsDirectory = [paths objectAtIndex:0]; 
    //NSString *path = [documentsDirectory stringByAppendingPathComponent:saveFileName]; 

    // - - - 

    // - - - Pull media from resources folder 

    NSString *path = [[NSBundle mainBundle] pathForResource:@"MyAudio" ofType:@"mp3"]; 

    // - - - 

    NSURL *url = [[NSURL alloc] initFileURLWithPath: path]; 

    [self setupAVPlayerForURL:url]; 
} 

-(void) setupAVPlayerForURL: (NSURL*) url { 
    AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil]; 
    AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset]; 

    player = [AVPlayer playerWithPlayerItem:anItem]; 
    [player addObserver:self forKeyPath:@"status" options:0 context:nil]; 
} 


- (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(@"AVPlayer Ready to Play"); 
     } else if (player.status == AVPlayerItemStatusUnknown) { 
      NSLog(@"AVPlayer Unknown"); 
     } 
    } 
} 

-(IBAction) BtnPlay:(id)sender { 
    [player play]; 
} 

-(IBAction) BtnPause:(id)sender { 
    [player pause]; 
} 

Scopri i Objective-C source code per un esempio funzionante di questo. Spero che questo aiuti!

-Aggiornamento 12/7/2015 Ora ho un Swift esempio del codice sorgente è possibile view here.

+0

NSString * percorso = [[NSBundle mainBundle] pathForResource: @ "MyAudio" ofType: @ "mp3"]; puoi spiegare questa linea per favore .. da dove stai recuperando mp3 .. – ChenSmile

+0

@stitz hai una soluzione per lo stesso per swift con AVPlayer? Sto affrontando lo stesso problema –

+1

@PenkeySuresh. Certo che faccio: https://github.com/davestitz/iOS-AvPlayer-Swift-Demo – stitz

3

Sì, è possibile scaricare e salvare il file .mp3 (o qualsiasi tipo di file) nella directory NSDocument e quindi è possibile ritirare e riprodurre utilizzando AVAudioPlayer.

NSString *downloadURL=**your url to download .mp3 file** 

NSURL *url = [NSURLURLWithString:downloadURL]; 

NSURLConnectionalloc *downloadFileConnection = [[[NSURLConnectionalloc] initWithRequest:  [NSURLRequestrequestWithURL:url] delegate:self] autorelease];//initialize NSURLConnection 

NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 

NSString *fileDocPath = [NSStringstringWithFormat:@"%@/",docDir];//document directory path 

[fileDocPathretain]; 

NSFileManager *filemanager=[ NSFileManager defaultManager ]; 

NSError *error; 

if([filemanager fileExistsAtPath:fileDocPath]) 
{ 

//just check existence of files in document directory 
} 

NSURLConnection is used to download the content.NSURLConnection Delegate methods are used to support downloading. 

(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 

} 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
NSFileManager *filemanager=[NSFileManagerdefaultManager]; 
if(![filemanager fileExistsAtPath:filePath]) 
{ 
[[NSFileManagerdefaultManager] createFileAtPath:fileDocPath contents:nil attributes:nil]; 

} 
NSFileHandle *handle = [NSFileHandlefileHandleForWritingAtPath:filePath]; 

[handle seekToEndOfFile]; 

[handle writeData:data]; 

[handle closeFile]; 
} 

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
UIAlertView *alertView=[[UIAlertViewalloc]initWithTitle:@”"message: 
[NSStringstringWithFormat:@"Connection failed!\n Error - %@ ", [error localizedDescription]] delegate:nilcancelButtonTitle:@”Ok”otherButtonTitles:nil]; 
    [alertView show]; 
    [alertView release]; 
    [downloadFileConnectioncancel];//cancel downloding 
    } 

Recuperare l'scaricato Audio & Play:

NSString *docDir1 = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 

    NSString *myfilepath = [docDir1 stringByAppendingPathComponent:YourAudioNameinNSDOCDir]; 

    NSLog(@”url:%@”,myfilepath); 

    NSURL *AudioURL = [[[NSURLalloc]initFileURLWithPath:myfilepath]autorelease]; 

Basta scrivere il codice per riprodurre l'audio utilizzando URL_audio

Mi piacerebbe sapere se u avere qualsiasi chiarimento in proposito.

Grazie

+0

Grazie per il codice di esempio.Ho bisogno di usare AVPlayer invece di AVAudioPlayer per questo progetto. – stitz

+0

Funzionerà correttamente se cercherò di riprodurre audio con AVPlayer subito dopo aver avviato la richiesta (o aver ricevuto il primo blocco)? Cosa succederà se la mia velocità di download non è sufficiente per la riproduzione in tempo reale? –

+1

Ehi @PavelAlexeev Sto provando a fare una cosa molto simile ora. Hai mai fatto funzionare qualcosa del genere? –

1

la sua molto difficile da giocare una canzone utilizzando un AVPlayer perché non si utilizza un lettore MPMoviePlayerController. Ho una canzone da ascoltare dalla directory dei documenti. Sto pubblicando un codice che si riferisce a questo. Funziona bene e anche tu direttamente da url live.

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *publicDocumentsDir = [paths objectAtIndex:0]; 
NSString *dataPath = [publicDocumentsDir stringByAppendingPathComponent:@"Ringtone"]; 
NSString *fullPath = [dataPath stringByAppendingPathComponent:[obj.DownloadArray objectAtIndex:obj.tagvalue]]; 
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO]; 


NSURL *url = [NSURL fileURLWithPath:fullPath]; 

videoPlayer =[[MPMoviePlayerController alloc] initWithContentURL: url]; 
[[videoPlayer view] setFrame: [self.view bounds]]; 
[vvideo addSubview: [videoPlayer view]]; 


videoPlayer.view.frame=CGRectMake(0, 0,260, 100); 
videoPlayer.view.backgroundColor=[UIColor clearColor]; 
videoPlayer.controlStyle = MPMovieControlStyleFullscreen; 
videoPlayer.shouldAutoplay = YES; 
[videoPlayer play]; 
videoPlayer.repeatMode=YES; 


NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 
[notificationCenter addObserver:self selector:@selector(moviePlayerEvent:) name:MPMoviePlayerLoadStateDidChangeNotification object:videoPlayer]; 


/* NSNotificationCenter *notificationCenter1 = [NSNotificationCenter defaultCenter]; 
[notificationCenter addObserver:self selector:@selector(moviePlayerEvent1:) name:MPMoviePlaybackStateStopped object:videoPlayer]; 
*/ 
[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(playbackStateChange:) 
              name:MPMoviePlayerLoadStateDidChangeNotification 
              object:videoPlayer]; 
} 

-(void)playbackStateChange:(NSNotification*)notification{ 

if([[UIApplication sharedApplication]respondsToSelector:@selector(setStatusBarHidden: withAnimation:)]) 
    { 
     [[UIApplication sharedApplication] setStatusBarHidden:NO 
              withAnimation:UIStatusBarAnimationNone]; 
    } 
    else 
    { 

     [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]; 
    } 
} 

-(void)moviePlayerEvent:(NSNotification*)aNotification{ 


    [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:NO]; 


} 

    -(void)moviePlayerEvent1:(NSNotification*)aNotification{ 

[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:NO]; 

} 
+0

La classe MPMoviePlayerController è obsoleta in iOS 9. https://developer.apple.com/reference/mediaplayer/mpmovieplayercontroller – RenniePet

9

ho avuto AVPlayer a lavorare con l'URL locale anteponendo file:// al mio url locale

NSURL * localURL = [NSURL URLWithString:[@"file://" stringByAppendingString:YOUR_LOCAL_URL]]; 
AVPlayer * player = [[AVPlayer alloc] initWithURL:localURL]; 
+0

Questo risolve il mio problema. Assicurati di controllare se l'aggiunta di "file: //" all'inizio del tuo percorso risolve il problema. – Jonathan

+0

Invece di NSURL * localURL = [NSURL URLWithString: [@ "file: //" stringByAppendingString: YOUR_LOCAL_URL]]; puoi scrivere NSURL * localURL = [NSURL fileURLWithString: YOUR_LOCAL_URL]; – MARTIN

2

Prova questa

NSString*thePath=[[NSBundle mainBundle] pathForResource:@"yourVideo" ofType:@"MOV"]; 
NSURL*theurl=[NSURL fileURLWithPath:thePath]; 
Problemi correlati