ios音頻播放以及時間顯示

主要實現的功能爲:音頻播放,音頻播放時自定義動畫以及音頻時間顯示

一、頭文件和代理添加

在.h文件中添加

#import <AVFoundation/AVFoundation.h>
<AVAudioPlayerDelegate,infoRecordViewDelegate//自定義播放界面的代理>

二、在.h文件中聲明

@property (nonatomic,strong) playRecordView *playRecView;//錄音

@property (nonatomic,strong) UILabel *title;

@property (nonatomic,strong) UIImageView *recordPhoto;

@property (nonatomic,strong) UILabel *lbltime;

@property (nonatomic,strong) UITapGestureRecognizer *tapPlayGesture;//點擊播放手勢
@property (nonatomic,strong) UITapGestureRecognizer *tapCloseGesture;//點擊添加關閉手勢
@property (nonatomic,strong) UITapGestureRecognizer *tapShowGesture;//點擊添加展示手勢

@property (nonatomic,assign) NSInteger countNum;//錄音計時(秒)
@property (nonatomic,strong) NSTimer *playTimer;//控制播放時長顯示更新
@property (nonatomic,strong) NSString *timeString;//播放時間

三、播放界面佈局

#pragma mark - playRecView界面佈局
- (UILabel *)titleInit
{
    if (!_title) {
        self.title = [[UILabel alloc]init];
        self.title.text = @"錄音";
        [self addSubview:self.title];

        [self.title mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(self).offset(0);
            make.centerY.mas_equalTo(self.centerY).offset(0);
            make.width.mas_equalTo(60);
        }];
    }
    return self.title;
}

- (UIImageView *)recordImageViewInit
{
    if (!_recordPhoto) {
//        self.recordPhoto = [[UIImageView alloc]init];
//        self.recordPhoto.image = [UIImage imageNamed:@"playRecord0.png"];

        //自定義動畫
        self.recordPhoto = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"playRecord0"]];
//        self.recordPhoto.size = CGSizeMake(SCREEN_WIDTH * 0.9 - 10 - 60,SCREEN_HEIGHT * 0.06);


        NSArray *picArray = @[[UIImage imageNamed:@"playRecord1"],
                              [UIImage imageNamed:@"playRecord2"],
                              [UIImage imageNamed:@"playRecord3"],];


        [self.recordPhoto setAnimationImages:picArray];
        //    self.recordPhoto.contentMode = UIViewContentModeScaleAspectFit;
        [self.recordPhoto setAnimationDuration:1.5];
        [self.recordPhoto setAnimationRepeatCount:0];

        [self addSubview:self.recordPhoto];


        [self.recordPhoto mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(self.title.mas_right).offset(0);
            make.centerY.mas_equalTo(self.centerY).offset(0);
            make.width.mas_equalTo(SCREEN_WIDTH * 0.9 - 10 - 60);
            make.height.mas_equalTo(SCREEN_HEIGHT * 0.06);
        }];
    }
    return self.recordPhoto;
}

- (UILabel *)lbltimeInit
{
    if (!_lbltime) {
        self.lbltime = [[UILabel alloc]init];
        self.lbltime.textColor = MF_ColorFromRGBA2(0x333333, 1);
        self.lbltime.text = @"00:00";
        [self.lbltime setHidden:YES];

        [self addSubview:self.lbltime];
        [self.lbltime mas_makeConstraints:^(MASConstraintMaker *make) {
            make.right.mas_equalTo(self.recordPhoto.mas_right).offset(0);
            make.centerY.mas_equalTo(self.recordPhoto.centerY).offset(0);
            make.size.mas_equalTo(CGSizeMake(60, 30));
        }];
    }
    return _lbltime;
}

四、播放界面

在.m文件中添加

#define kSandboxPathStr [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
- (void)viewWillDisappear:(BOOL)animated
{
    [self stopAllMusic];
}
- (void)viewDidDisappear:(BOOL)animated
{
    //停止播放動畫
    [self stopPlayAnimation];
}
#pragma mark - 數據初始化
- (void)setData
{
            _tapPlayGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(playRecordGestureClick:)];
        self.playRecView = [[playRecordView alloc]init];
        self.playRecView.recordPhoto.userInteractionEnabled = YES;
        self.playRecView.recordPhoto.tag = 20000 + i;
        self.playRecView.tag = 20000 + i;
        [[self.playRecView.recordPhoto viewWithTag:20000 + i] addGestureRecognizer:_tapPlayGesture];



        self.playRecView.frame = CGRectMake(SCREEN_WIDTH * 0.05, 60 + SCREEN_HEIGHT * 0.08 * i, SCREEN_WIDTH * 0.9 - 10, SCREEN_HEIGHT * 0.08);
        [self.recordBackView addSubview:self.playRecView];
}
//播放手勢觸發
- (void)playRecordGestureClick:(UITapGestureRecognizer *)playGesture
{
    if(playImageView && playImageView.isAnimating)
    {

        [_recordView stopAllMusic];
        [playImageView stopAnimating];
        for (playRecordView *playRecView in _recordBackView.subviews) {
            if (playRecView.tag == playImageView.tag) {
                [playRecView.lbltime setHidden:YES];

                playRecView.lbltime.text = @"00:00";
            }
        }
        [self.playTimer invalidate];

    }else{
        playImageView = (UIImageView*)playGesture.view;
        NSInteger index = playImageView.tag - 20000;

        [playImageView startAnimating];

        [_recordView playRecord:[self.recordArray objectAtIndex:index]];

        //獲取總時間
        [self.playTimer fire];

    }

    NSLog(@"%ld",(long)index);


}

//停止播放動畫代理
- (void)stopPlayAnimation
{
    if(playImageView && playImageView.isAnimating)
    {
        for (playRecordView *playRecView in _recordBackView.subviews) {
            if (playRecView.tag == playImageView.tag) {
                [playRecView.lbltime setHidden:YES];
                playRecView.lbltime.text = @"00:00";
            }
        }
        [self.playTimer invalidate];

        [playImageView stopAnimating];
    }
}
-(void)sendTotalTime:(NSTimeInterval)totalTime currentTime:(NSTimeInterval)currentTime
{
    self.countNum = 0;
    NSTimeInterval timeInterval =1 ;
    //    1s
    self.playTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval  target:self selector:@selector(updatePlayTimerValue)  userInfo:nil  repeats:YES];

    tduration = totalTime;

}

-(void)updatePlayTimerValue
{
    self.countNum += 1;
    NSUInteger seconds = (NSUInteger)round(tduration);
    _timeString = [NSString stringWithFormat:@"00:%02lu",seconds % 60 - self.countNum];

    for (playRecordView *playRecView in _recordBackView.subviews) {
        if (playRecView.tag == playImageView.tag) {
            [playRecView.lbltime setHidden:NO];
            if (self.countNum >= (seconds % 60)) {
                playRecView.lbltime.text = @"00:00";
            }else{
                playRecView.lbltime.text = _timeString;
            }
        }
    }

}

五、recordView(播放方法:核心)

.h文件

@protocol infoRecordViewDelegate<NSObject>
@optional
//獲取錄音數據
-(void)getRecordData:(NSString *)path type:(NSString *)type fileName:(NSString *)fileName;//獲取數據
//停止播放動畫
- (void)stopPlayAnimation;

//發送時間
- (void)sendTotalTime:(NSTimeInterval)totalTime currentTime:(NSTimeInterval)currentTime;

@end

@interface infoRecordView : UIView<AVAudioPlayerDelegate>

@property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音頻播放器
@property (nonatomic,assign) NSInteger countNum;//錄音計時(秒)
@property (nonatomic,strong) NSTimer *playTimer;//控制播放時長顯示更新
@property (nonatomic,strong) NSString *timeString;//播放時間
@property (nonatomic,strong) UIButton *closeBtn; //關閉按鈕
@property (nonatomic,strong) UIView *playBackView;//播放動畫背景

@property (nonatomic,copy) NSString *cafPathStr;

@property (nonatomic,weak) id<infoRecordViewDelegate>delegate;

@property (nonatomic,strong) UIImageView *playAniImageView;//播放動畫

- (void)playRecord:(NSString *)path view:(UIView *)view;

- (void)playRecord:(NSString *)path;

- (void)stopAllMusic;//停止播放

.m文件

#pragma mark - 播放
- (void)playRecord:(NSString *)path view:(UIView *)view
{
    [self stopAllMusic];

    AVAudioSession *audioSession=[AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];  //此處需要恢復設置回放標誌,否則會導致其它播放聲音也會變小

    NSString *newPath = [path substringFromIndex:1];//路徑第一位多了個/

    [self playMusicWithUrl:[NSURL URLWithString:newPath]];
}

//查看歷史使用
- (void)playRecord:(NSString *)path
{
    [self stopAllMusic];

    AVAudioSession *audioSession=[AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];  //此處需要恢復設置回放標誌,否則會導致其它播放聲音也會變小

    NSString *newPath = [path substringFromIndex:1];//路徑第一位多了個/

    [self playMusicWithUrl:[NSURL URLWithString:newPath]];

}

- (void)stopPlayRecord
{
    [self stopMusicWithUrl:[NSURL URLWithString:self.cafPathStr]];
}
-(void)deleteOldRecordFile{
    NSFileManager* fileManager=[NSFileManager defaultManager];

    BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:self.cafPathStr];
    if (!blHave) {
//        NSLog(@"不存在");
        return ;
    }else {
//        NSLog(@"存在");
        BOOL blDele= [fileManager removeItemAtPath:self.cafPathStr error:nil];
        if (blDele) {
//            NSLog(@"刪除成功");
        }else {
//            NSLog(@"刪除失敗");
        }
    }
}


-(void)deleteOldRecordFileAtPath:(NSString *)pathStr{
    NSFileManager* fileManager=[NSFileManager defaultManager];

    BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:pathStr];
    if (!blHave) {
//        NSLog(@"不存在");
        return ;
    }else {
//        NSLog(@"存在");
        BOOL blDele= [fileManager removeItemAtPath:self.cafPathStr error:nil];
        if (blDele) {
//            NSLog(@"刪除成功");
        }else {
//            NSLog(@"刪除失敗");
        }
    }
}

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
//    NSLog(@"delegate--播放完畢----------------------");

    //停止播放動畫代理
    [self.delegate stopPlayAnimation];

    [HUD hide:YES];
}

#pragma mark - AudioPlayer方法

/**
 *播放音樂文件
 */
- (BOOL)playMusicWithUrl:(NSURL *)fileUrl
{
    //其他播放器停止播放
    [self stopAllMusic];

    if (!fileUrl) return NO;

    AVAudioSession *session=[AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];  //此處需要恢復設置回放標誌,否則會導致其它播放聲音也會變小
    [session setActive:YES error:nil];

    NSError *error;

    _audioPlayer = [self musices][fileUrl];

#warning 不能加入全局異常斷點,不然會卡在這裏
    if (!_audioPlayer) {
        //2.2創建播放器
        _audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:fileUrl error:&error];

    }

    _audioPlayer.delegate = self;

    if (![_audioPlayer prepareToPlay]){
        NSLog(@"緩衝失敗--");
        //        [self myToast:@"播放器緩衝失敗"];
        return NO;
    }

    if (![_audioPlayer isPlaying]){
        //串行同步
        dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);

        dispatch_sync(queue, ^{
            [self.delegate sendTotalTime:_audioPlayer.duration currentTime:_audioPlayer.currentTime];
        });
        dispatch_sync(queue, ^{
            //播放
            [_audioPlayer play];
        });

    }
    //2.4存入字典
    [self musices][fileUrl]=_audioPlayer;

//    NSLog(@"musices:%@ musices",self.musices);
      return YES;//正在播放,那麼就返回YES
}

/**
 *停止播放音樂文件
 */
- (void)stopMusicWithUrl:(NSURL *)fileUrl{
    if (!fileUrl) return;//如果沒有傳入文件名,那麼就直接返回

    //1.取出對應的播放器
    AVAudioPlayer *player=[self musices][fileUrl];

    //2.停止
    if ([player isPlaying]) {
        [player stop];
//        NSLog(@"播放結束:%@--------",fileUrl);
    }

    if ([[self musices].allKeys containsObject:fileUrl]) {

        [[self musices] removeObjectForKey:fileUrl];
    }
}

//停止所有正在播放的音頻
- (void)stopAllMusic
{

    if ([self musices].allKeys.count > 0) {
        for ( NSString *playID in [self musices].allKeys) {

            AVAudioPlayer *player=[self musices][playID];
            [player stop];            
        }
    }

    if(HUD){
        [HUD hide:YES];
    }


}

- (NSMutableDictionary *)musices
{
    if (_musices==nil) {
        _musices=[NSMutableDictionary dictionary];
    }
    return _musices;
}

PS:ios錄音功能實現http://blog.csdn.net/fantasy_jun/article/details/77894709

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章