項目當中用到了音頻播放器,所以就參考官方文檔,寫了一個,代碼如下:
.h
#import <UIKit/UIKit.h> @interface hAudioPlayViewController : UIViewController @property(nonatomic,strong)NSString *titleStr;//音樂名字 @property(nonatomic,strong)NSString *kMusicFile;//音樂文件 @property(nonatomic,strong)NSString *nameStr;//演唱者 @end
.m
#import "hAudioPlayViewController.h" #import <AVFoundation/AVFoundation.h> @interface hAudioPlayViewController ()<CustomNavigationBarDelegate,AVAudioPlayerDelegate> @property (nonatomic,strong) AVAudioPlayer *audioPlayer;//播放器 @property (weak, nonatomic) IBOutlet UIImageView *bgImg; @property (weak, nonatomic) IBOutlet UILabel *nameLab; @property (weak, nonatomic) IBOutlet UIButton *playBtn; @property (weak, nonatomic) IBOutlet UIProgressView *progressV; @property (weak ,nonatomic) NSTimer *timer;//進度更新定時器 @property (weak, nonatomic) IBOutlet UILabel *timeLab; @property (assign, nonatomic) BOOL isPlay; @end @implementation hAudioPlayViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.view.backgroundColor =BackgroundColor; CustomNavigationBar *nav = [[CustomNavigationBar alloc]initWithFrame:CGRectMake(0, 0, KscreenW, NavHeight) withTitle:[NSString stringWithFormat:@"%@",self.titleStr] withLeftBtnHidden:NO withRightBtn:YES]; nav.delegate = self; [self.view addSubview:nav]; self.isPlay = NO; [self creatUI]; } -(void)leftBtnAction:(id)sender { [self.navigationController popViewControllerAnimated:YES]; [self.audioPlayer pause]; } -(void)creatUI { self.nameLab.text = self.nameStr; [self play]; self.playBtn.selected = YES; } -(NSTimer *)timer{ if (!_timer) { _timer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateProgress) userInfo:nil repeats:true]; } return _timer; } /** * 創建播放器 * * @return 音頻播放器 */ -(AVAudioPlayer *)audioPlayer{ if (!_audioPlayer) { //這段代碼是設置聲道,防止設備在揚聲器的狀態下沒有聲音 AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; NSURL *url = [NSURL URLWithString:self.kMusicFile]; //將文件先下載到本地,然后再播放 NSData *audioData = [NSData dataWithContentsOfURL:url]; NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *filePath = [NSString stringWithFormat:@"%@/%@.mp3",docDirPath,@"temp"]; [audioData writeToFile:filePath atomically:YES]; NSError *error=nil; //初始化播放器,注意這里的Url參數只能時文件路徑,不支持HTTP Url _audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:filePath] error:&error]; //設置播放器屬性 _audioPlayer.numberOfLoops=0;//設置為0不循環 _audioPlayer.delegate=self; [_audioPlayer prepareToPlay];//加載音頻文件到緩存 if(error){ NSLog(@"初始化播放器過程發生錯誤,錯誤信息:%@",error.localizedDescription); return nil; } } return _audioPlayer; } /** * 播放音頻 */ -(void)play{ if (![self.audioPlayer isPlaying]) { [self.audioPlayer play]; self.timer.fireDate=[NSDate distantPast];//恢復定時器 } } /** * 暫停播放 */ -(void)pause{ if ([self.audioPlayer isPlaying]) { [self.audioPlayer pause]; self.timer.fireDate=[NSDate distantFuture];//暫停定時器,注意不能調用invalidate方法,此方法會取消,之后無法恢復 } } /** * 點擊播放/暫停按鈕 * * @param sender 播放/暫停按鈕 */ - (IBAction)playClick:(UIButton *)sender { sender.selected = !sender.selected; if (sender.selected==self.isPlay) { [self pause]; }else { [self play]; } } /** * 更新播放進度 */ -(void)updateProgress{ float progress= self.audioPlayer.currentTime /self.audioPlayer.duration; [self.progressV setProgress:progress animated:true]; int current = (int)self.audioPlayer.currentTime; int duration = (int)self.audioPlayer.duration; self.timeLab.text = [NSString stringWithFormat:@"%@/%@",[self timeFormatted:current],[self timeFormatted:duration]]; } /** * 把秒轉換為時間格式 */ -(NSString *)timeFormatted:(int)totalSeconds { int seconds = totalSeconds % 60; int minutes = (totalSeconds / 60) % 60; // int hours = totalSeconds / 3600; return [NSString stringWithFormat:@"%02d:%02d",minutes, seconds]; } #pragma mark - 播放器代理方法 -(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{ NSLog(@"音樂播放完成..."); }
相關的時間轉化,暫停與播放等基本功能已完善,不過沒有做其他更精細化的操作,譬如保存進度,第二次進來繼續上次的進度播放;快進等操作!
附
官方文檔地址:
https://developer.apple.com/documentation/avfoundation/avaudioplayer?language=objc
碰到問題,設備在揚聲器下沒有聲音:
1,原因:
沒有設置聲道;
AVAudioSession是一個單例,無需實例化即可直接使用。AVAudioSession在各種音頻環境中起着非常重要的作用
針對不同的音頻應用場景,需要設置不同的音頻回話分類
2,解決方法:
在初始化AVAudioPlayer之前,設置聲道,代碼如下:
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
效果如下:
上面描述的是AudioPlayer的用法,下面說下AVPlayer的用法,他們兩直接的區別如果同時播放音頻的話,AudioPlayer比較適合播放本地的文件,而AVPlayer則可以播放在線的音頻文件,當然也可以播放視頻文件,這里先不說,比較簡單,代碼如下:
#import "hAVPlayerViewController.h" #import <AVFoundation/AVFoundation.h> @interface hAVPlayerViewController ()<CustomNavigationBarDelegate> @property (weak, nonatomic) IBOutlet UILabel *titleLab; @property (weak, nonatomic) IBOutlet UIButton *playBtn; @property (weak, nonatomic) IBOutlet UILabel *timeLab; @property (assign, nonatomic) BOOL isPlay;//用來標記是否播放 @property (weak, nonatomic) IBOutlet UIProgressView *progress; //播放器 @property (nonatomic,strong)AVPlayer *avPlayer; //監控進度 @property (nonatomic,strong)NSTimer *avTimer; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *imgTop; @end @implementation hAVPlayerViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.view.backgroundColor =BackgroundColor; CustomNavigationBar *nav = [[CustomNavigationBar alloc]initWithFrame:CGRectMake(0, 0, KscreenW, NavHeight) withTitle:[NSString stringWithFormat:@"%@",self.model.title] withLeftBtnHidden:NO withRightBtn:YES]; nav.delegate = self; [self.view addSubview:nav]; self.imgTop.constant = NavHeight; self.isPlay = NO; //mp3播放網址 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@",self.model.music_url]]; //播放器初始化 self.avPlayer = [[AVPlayer alloc]initWithURL:url]; /* //設置播放器初始音量 self.avPlayer.volume =1; //初始0音量 self.volume.value =5.0f; //設置最大值最小值音量 self.volume.maximumValue =10.0f; self.volume.minimumValue =0.0f; */ //監控播放進度 self.avTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timer) userInfo:nil repeats:YES]; self.titleLab.text = [NSString stringWithFormat:@"%@",self.model.title]; self.playBtn.selected = YES; [self.avPlayer play]; } -(void)leftBtnAction:(id)sender { [self.avPlayer pause]; [self.navigationController popViewControllerAnimated:YES]; } //監控播放進度方法 - (void)timer { float progress= CMTimeGetSeconds(self.avPlayer.currentItem.currentTime) / CMTimeGetSeconds(self.avPlayer.currentItem.duration); [self.progress setProgress:progress animated:true]; int current = (int)CMTimeGetSeconds(self.avPlayer.currentItem.currentTime); int duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration); self.timeLab.text = [NSString stringWithFormat:@"%@/%@",[self timeFormatted:current],[self timeFormatted:duration]]; } /** * 把秒轉換為時間格式 */ -(NSString *)timeFormatted:(int)totalSeconds { int seconds = totalSeconds % 60; int minutes = (totalSeconds / 60) % 60; // int hours = totalSeconds / 3600; return [NSString stringWithFormat:@"%02d:%02d",minutes, seconds]; } //播放/暫停 - (IBAction)play:(id)sender { UIButton *btn = (UIButton *)sender; btn.selected = !btn.selected; if (btn.selected == self.isPlay) { [self.avPlayer pause]; }else{ [self.avPlayer play]; } }
僅做記錄!