English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Explicação detalhada do uso do player de música iOS DOUAudioStreamer

Há muito tempo não escrevi nada, recentemente o trabalho de overtime foi muito severo, hoje tentei encontrar tempo para organizar o reprodutor de música DOUAudioStreamer que usei, pois o projeto anterior usava AVPlayer, que também é bom, mas precisa de um tempo de cache antes de reproduzir, o chefe viu e pediu, que mude o cache para reprodução (quando há rede, clique no botão de reprodução e reproduza imediatamente), por que não dizer cedo? Por que não dizer cedo? Por que não dizer cedo? Como pode ser? Só posso perdoá-lo, continuar a escrever código...... (vamos direto ao ponto)

I. Importar biblioteca de terceiros

pod 'DOUAudioStreamer'

ou endereço de download do GitHup:https://github.com/douban/DOUAudioStreamer

II. Uso

1.Obter o arquivo NAKPlaybackIndicatorView e os arquivos MusicIndicator.h e MusicIndicator.m do demo e importar os cabeçalhos

//Reprodução de música
#import "DOUAudioStreamer.h"
#import "NAKPlaybackIndicatorView.h"
#import "MusicIndicator.h"
#import "Track.h"

Como na figura:

2.Criar uma classe Track para armazenar URLs de reprodução de música

3.Adicionar DOUAudioStreamer ao arquivo de interface.h e inicializar com singleton

+ (instancetype)sharedInstance ;
@property (nonatomic, strong) DOUAudioStreamer *streamer;

 

Como na figura:

No .m implementar:

static void *kStatusKVOKey = &kStatusKVOKey;
static void *kDurationKVOKey = &kDurationKVOKey;
static void *kBufferingRatioKVOKey = &kBufferingRatioKVOKey;
@property (strong, nonatomic) MusicIndicator *musicIndicator;
@property (nonatomic, strong) Track *audioTrack;
+ (instancetype)sharedInstance {
 static HYNEntertainmentController *_sharedMusicVC = nil;
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
  _sharedMusicVC = [[HYNEntertainmentController alloc] init];
  _sharedMusicVC.streamer = [[DOUAudioStreamer alloc] init];
 }); 
 return _sharedMusicVC;
}

 

Evento do botão de reprodução

#pragma mark ---Botão de reprodução de música
-(void)playMusicStart:(UIButton *)sender
{
  //Obter célula por meio de botão
  MusicCollectionViewCell *musicCell = (MusicCollectionViewCell *)[[sender superview] superview];
 if(_playFirst == 0){//_playFirst == 0 para reprodução inicial, outros para pausa
  NSURL *url = [NSURL URLWithString:HttpImgUrl(musicCell.model.musicUrl)];
  _audioTrack.audioFileURL = url;
  @try {
   [self removeStreamerObserver];
  }; @catch(id anException){ 
  }
  //Antes de reprodução no DOUAudioStreamer, deve ser configurado como nil
  _streamer = nil;
  _streamer = [DOUAudioStreamer streamerWithAudioFile:_audioTrack];
  [self addStreamerObserver];
  [_streamer play];
 }
 if([_streamer status] == DOUAudioStreamerPaused ||
  [_streamer status] == DOUAudioStreamerIdle){
  [sender setBackgroundImage:[UIImage imageNamed:@"music_play_icon"] forState:UIControlStateNormal];
  [_streamer play]; 
 }else{
  [sender setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal];
  [_streamer pause]; 
 }
 _playFirst++;
}

 

Para adicionar observador

- (void)addStreamerObserver {
 [_streamer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:kStatusKVOKey];
 [_streamer addObserver:self forKeyPath:@"duration" options:NSKeyValueObservingOptionNew context:kDurationKVOKey];
 [_streamer addObserver:self forKeyPath:@"bufferingRatio" options:NSKeyValueObservingOptionNew context:kBufferingRatioKVOKey]; 
}
/// destruição do player
- (void)dealloc{
 se (_streamer !=nil) {
  [_streamer pause];
  [_streamer removeObserver:self forKeyPath:@"status" context:kStatusKVOKey];
  [_streamer removeObserver:self forKeyPath:@"duration" context:kDurationKVOKey];
  [_streamer removeObserver:self forKeyPath:@"bufferingRatio" context:kBufferingRatioKVOKey];
  _streamer =nil;
 } 
}
- (void)removerObservadorDoStreamer {
 [_streamer removeObserver:self forKeyPath:@"status"];
 [_streamer removeObserver:self forKeyPath:@"duration"];
 [_streamer removeObserver:self forKeyPath:@"bufferingRatio"];
}
- (void)observarValorPelaChaveDoCaminho:(NSString *)chave do caminho do objeto:(id)object mudar:(NSDictionary *)mudar contexto:(void *)context {
 se (context == kStatusKVOKey) {
  [self performSelector:@selector(updateStatus)]
      onThread:[NSThread mainThread]
     withObject:nil
    waitUntilDone:NO];
 } else if (context == kDurationKVOKey) {
  [self performSelector:@selector(updateSliderValue:)
      onThread:[NSThread mainThread]
     withObject:nil
    waitUntilDone:NO];
 } else if (context == kBufferingRatioKVOKey) {
  [self performSelector:@selector(updateBufferingStatus)
      onThread:[NSThread mainThread]
     withObject:nil
    waitUntilDone:NO];
 } else {
  [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
 }
}
- (void)updateSliderValue:(id)timer {
}
-(void)updateBufferingStatus
{ 
}
- (void)updateStatus {
 //self.musicIsPlaying = NO;
 _musicIndicator.state = NAKPlaybackIndicatorViewStateStopped;
 switch ([_streamer status]) {
  case DOUAudioStreamerPlaying:
   // self.musicIsPlaying = YES;
   _musicIndicator.state = NAKPlaybackIndicatorViewStatePlaying;
   break;
  case DOUAudioStreamerPaused:
   break;
  case DOUAudioStreamerIdle:
   break;
  case DOUAudioStreamerFinished:
   break;
  case DOUAudioStreamerBuffering:
   _musicIndicator.state = NAKPlaybackIndicatorViewStatePlaying;
   break;  
  case DOUAudioStreamerError:
   break;
 } 
}

Desta forma, será possível reproduzir.

A exibição de música na tela de bloqueio, pausa a reprodução após a remoção do fone de ouvido, e monitoramento de eventos de interrupção de áudio

-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//Accept remote control
[self becomeFirstResponder];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
//This cannot be forgotten
-(BOOL)canBecomeFirstResponder{
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
//Music player
[self initPlayer];
}
#pragma mark =========================Music Playback==============================
//Music player
-(void)initPlayer
{
_audioTrack = [[Track alloc] init];
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
//Let the app support receiving remote control events
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
//Add notification, pause playback after pulling out the earphones
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil];
// Listen to audio interruption events
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasInterrupted:) name:AVAudioSessionInterruptionNotification object:session];
}
// Listen to audio interruption events
- (void)audioSessionWasInterrupted:(NSNotification *)notification
{
 //When interrupted
if (AVAudioSessionInterruptionTypeBegan == [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue])
{
[_streamer pause];
UIButton *btn = (UIButton *)[self.view viewWithTag:",
    "第44段": "sender = (UIButton2000];
[btn setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal];
}
else if (AVAudioSessionInterruptionTypeEnded == [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue])}}
{
}
}
// pausar reprodução após a remoção do fone de ouvido
-(void)routeChange:(NSNotification *)notification{
NSDictionary *dic=notification.userInfo;
int changeReason= [dic[AVAudioSessionRouteChangeReasonKey] intValue];
//igual a AVAudioSessionRouteChangeReasonOldDeviceUnavailable indica que a saída antiga não está disponível
if (changeReason==AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
AVAudioSessionRouteDescription *routeDescription=dic[AVAudioSessionRouteChangePreviousRouteKey];
AVAudioSessionPortDescription *portDescription= [routeDescription.outputs firstObject];
//o dispositivo original é fone de ouvido, então pause
if ([portDescription.portType isEqualToString:@"Headphones"]) {
[_streamer pause];
UIButton *btn = (UIButton *)[self.view viewWithTag:",
    "第44段": "sender = (UIButton2000];
[btn setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal];
}
}
}
//exibir música no bloqueio da tela (este método pode ser chamado ao clicar em reprodução, passando valores)
- (void)setupLockScreenInfoWithSing:(NSString *)sign WithSigner:(NSString *)signer WithImage:(UIImage *)image
{
// 1.obter centro de bloqueio da tela
MPNowPlayingInfoCenter *playingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
//Initialize a dictionary to store music information
NSMutableDictionary *playingInfoDict = [NSMutableDictionary dictionary];
// 2Set the song name
if (sign) {
[playingInfoDict setObject:sign forKey:MPMediaItemPropertyAlbumTitle];
}
// Set the artist name
if (signer) {
[playingInfoDict setObject:signer forKey:MPMediaItemPropertyArtist];
}
// 3Set the cover image
//UIImage *image = [self getMusicImageWithMusicId:self.currentModel];
if (image) {
MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:image];
[playingInfoDict setObject:artwork forKey:MPMediaItemPropertyArtwork];
}
// 4Set the total duration of the song
//[playingInfoDict setObject:self.currentModel.detailDuration forKey:MPMediaItemPropertyPlaybackDuration];
//Assign music information to the nowPlayingInfo property of the lock screen center
playingInfoCenter.nowPlayingInfo = playingInfoDict;
// 5.Enable remote interaction
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
//Lock screen operation
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
UIButton *sender = (UIButton *)[self.view viewWithTag:",
    "第44段": "sender = (UIButton2000];
switch (receivedEvent.subtype) {//Verificar se é controle remoto
case UIEventSubtypeRemoteControlPause:
[[HYNEntertainmentController sharedInstance].streamer pause];
[sender setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal];
break;
case UIEventSubtypeRemoteControlStop:
break;
case UIEventSubtypeRemoteControlPlay:
[[HYNEntertainmentController sharedInstance].streamer play];
[sender setBackgroundImage:[UIImage imageNamed:@"music_play_icon"] forState:UIControlStateNormal];
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
break;
case UIEventSubtypeRemoteControlNextTrack:
break;
case UIEventSubtypeRemoteControlPreviousTrack:
break;
default:
break;
}
}
}

Imagem geral:

A imagem acima é o estado não reproduzido

A imagem acima é o estado de reprodução

A imagem acima é o estado de bloqueio da tela

Deve não haver nada mais a adicionar, por enquanto vamos parar, se houver algo que não esteja bem, você pode discutir na seção de comentários abaixo, obrigado pelo apoio ao tutorial Gritar.

Você também pode gostar