标签:avaudioplayer mpmovieplayerviewcon nsnotificationcenter 音乐播放器 媒体播放
本章主要接到上次的文章讲音频播放,因为音频播放没有对应的播放视图控件,所以本例子自绘了一个简单的音乐播放界面,包括返回、暂停/播放、进度控制等。
(暂停/播放 播放进度拖拉 返回)
1.接上次的流程新建一个音乐播放类,模拟MPMoviePlayerViewController的实现;
2.播放音频的时使用IOS内置的类AVAudioPlayer,该类支持播放wav.mp3等格式的音乐,其对应的代理类为AVAudioPlayerDelegate;
3.对于这种初始化赋值代码:self._buttonPlayPause = [[UIButton alloc] init];突然想到这种赋值会存在内存泄露 ,因为分配内存直接赋值给属性变量,变量retain两次最后却只release一次。所以以前的好多代码都有问题。汗!!!
4.NSNotificationCenter添加监视时注意object不要为空而要设为nil,不能会导致难发现的内存奔溃问题。
//
// MusicPlayerViewController.h
// MediaPlayer
//
// Created by God Lin on 14/12/15.
// Copyright (c) 2014年 arbboter. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface MusicPlayerViewController : UIViewController <AVAudioPlayerDelegate>
{
AVAudioPlayer* _audioPlayer;
UIButton* _buttonPlayPause;
UIButton* _buttonReturn;
UIImage* _imagePause;
UIImage* _imagePlay;
UIImage* _imageReturn;
UISlider* _sliderPlayer;
NSURL* _urlMusic;
NSTimer* _timerPlayProcess;
BOOL _bPlay;
UITextView* _textViewInfo;
NSString* _titleMusic;
}
@property (nonatomic, retain) AVAudioPlayer* _audioPlayer;
@property (nonatomic, retain) UIButton* _buttonPlayPause;
@property (nonatomic, retain) UIButton* _buttonReturn;
@property (nonatomic, retain) UISlider* _sliderPlayer;
@property (nonatomic, retain) NSURL* _urlMusic;
@property (nonatomic, retain) UIImage* _imagePause;
@property (nonatomic, retain) UIImage* _imagePlay;
@property (nonatomic, retain) UIImage* _imageReturn;
@property (nonatomic, readwrite) BOOL _bPlay;
@property (nonatomic, retain) NSTimer* _timerPlayProcess;
@property (nonatomic, retain) UITextView* _textViewInfo;
@property (nonatomic, retain) NSString* _titleMusic;
-(id)initWithContentURL:(NSURL*)url;
-(void)setContentURL:(NSURL*)url;
@end
void AudioFinishedCallBack(SystemSoundID idSound, void* data);
//
// MusicPlayerViewController.m
// MediaPlayer
//
// Created by God Lin on 14/12/15.
// Copyright (c) 2014年 arbboter. All rights reserved.
//
#import "MusicPlayerViewController.h"
@interface MusicPlayerViewController ()
@end
@implementation MusicPlayerViewController
@synthesize _audioPlayer, _urlMusic;
@synthesize _buttonPlayPause, _buttonReturn;
@synthesize _sliderPlayer, _titleMusic;
@synthesize _imagePause, _imageReturn, _imagePlay;
@synthesize _bPlay, _timerPlayProcess, _textViewInfo;
// 布局
-(void) doRotateAction:(NSNotification *) notification
{
[self relayout];
}
-(void)relayout
{
CGFloat x = self.view.frame.origin.x;
CGFloat y = self.view.frame.origin.y + 20;
CGFloat w = self.view.frame.size.width;
CGFloat h = self.view.frame.size.height - 20;
CGFloat x1 = 0;
CGFloat y1 = 0;
CGFloat w1 = 0;
CGFloat h1 = 0;
UIImage* image = self._imagePause;
if(w < h)
{
image = [UIImage imageNamed:@"oca.jpeg"];
}
else
{
image = [UIImage imageNamed:@"flower.jpg"];
}
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
image = self._imageReturn;
x1 = x + 5;
y1 = y + 5;
w1 = image.size.width;
h1 = image.size.height;
self._buttonReturn.frame = CGRectMake(x1, y1, w1, h1);
image = self._imagePause;
x1 = x + 5;
y1 = (y + h) - (image.size.height + 5);
w1 = image.size.width;
h1 = image.size.height;
self._buttonPlayPause.frame = CGRectMake(x1, y1, w1, h1);
x1 += image.size.width ;
w1 = x + w - 5 - x1;
self._sliderPlayer.frame = CGRectMake(x1, y1, w1, h1);
x1 = x + 5;
y1 = y + h/4;
w1 = w - 10;
h1 = h/2;
NSArray* fontArray = [UIFont familyNames];
NSString* fontName = [fontArray objectAtIndex:arc4random()%[fontArray count]];
_textViewInfo.font = [UIFont fontWithName:fontName size:h1/10];
_textViewInfo.frame = CGRectMake(x1, y1, w1, h1);
_textViewInfo.editable = NO;
_textViewInfo.textAlignment = NSTextAlignmentCenter;
_textViewInfo.backgroundColor = [UIColor clearColor];
}
// 播放界面控件
-(void)onDragPlayProcess
{
[self._audioPlayer setCurrentTime:self._sliderPlayer.value];
}
-(void)onPlayProcess
{
self._sliderPlayer.value = self._audioPlayer.currentTime;
NSInteger nTime = _sliderPlayer.value;
NSInteger nMaxTime = _sliderPlayer.maximumValue;
NSString* info = [[NSString alloc] initWithFormat:@"%@\n%02ld:%02ld - %02ld:%02ld", _titleMusic, nTime/60, nTime%60, nMaxTime/60, nMaxTime%60];
_textViewInfo.text = info;
[info release];
}
// 设置播放的文件
-(id)initWithContentURL:(NSURL*)url
{
self = [super init];
if(self)
{
[self setContentURL:url];
}
return self;
}
-(void)setContentURL:(NSURL*)url
{
self._urlMusic = url;
}
// 启动播放,画面出现前
-(void)viewWillAppear:(BOOL)animated
{
[self onPlay];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self._imagePlay = [UIImage imageNamed:@"play.png"];
self._imagePause = [UIImage imageNamed:@"pause.png"];
self._imageReturn = [UIImage imageNamed:@"return.png"];
// 突然想到这种赋值会存在内存泄露 -> 分配内存直接赋值给属性变量
// 因为retain两次最后却只release一次,所以以前的好多都有问题
// 汗!!!
UIButton* button = nil;
button = [[UIButton alloc] init];
self._buttonPlayPause = button;
[button release];
[self.view addSubview:self._buttonPlayPause];
[self._buttonPlayPause setImage:self._imagePause forState:UIControlStateNormal];
[self._buttonPlayPause addTarget:self action:@selector(onPlayPause) forControlEvents:UIControlEventTouchUpInside];
button = [[UIButton alloc] init];
self._buttonReturn = button;
[button release];
[self.view addSubview:self._buttonReturn];
[self._buttonReturn setImage:self._imageReturn forState:UIControlStateNormal];
[self._buttonReturn addTarget:self action:@selector(onStop) forControlEvents:UIControlEventTouchUpInside];
UISlider* slider = [[UISlider alloc] init];
self._sliderPlayer = slider;
[slider release];
[self.view addSubview:self._sliderPlayer];
[self._sliderPlayer addTarget:self action:@selector(onDragPlayProcess) forControlEvents:UIControlEventValueChanged];
UITextView* textView = [[UITextView alloc] init];
self._textViewInfo = textView;
[textView release];
[self.view addSubview:_textViewInfo];
[self relayout];
// 切屏
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(doRotateAction:)
name:UIDeviceOrientationDidChangeNotification
object:self];
}
-(void)onPlay
{
if(!_bPlay)
{
NSError* error;
self._bPlay = YES;
AVAudioPlayer* player = [[AVAudioPlayer alloc] initWithContentsOfURL:self._urlMusic error:&error];
self._audioPlayer = player;
[player release];
self._audioPlayer.delegate = self;
self._timerPlayProcess = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(onPlayProcess) userInfo:nil repeats:YES];
//self._audioPlayer;
self._sliderPlayer.maximumValue = 0.0f;
// 设置播放时长
self._sliderPlayer.maximumValue = self._audioPlayer.duration;
[self._audioPlayer play];
// 非法音频
if(_sliderPlayer.maximumValue == 0)
{
[self onStop];
}
[self onPlayProcess];
}
}
-(void)onStop
{
[self dismissViewControllerAnimated:YES completion:nil];
[self._audioPlayer stop];
[self._timerPlayProcess invalidate];
_bPlay = NO;
}
-(void)onPlayPause
{
UIImage* image = nil;
_bPlay = !_bPlay;
if(_bPlay)
{
image = self._imagePause;
[self._audioPlayer play];
}
else
{
image = self._imagePlay;
[self._audioPlayer pause];
}
[self._buttonPlayPause setImage:image forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)dealloc
{
[_buttonReturn release];
[_buttonPlayPause release];
[_imageReturn release];
[_imagePause release];
[_imagePlay release];
[_audioPlayer release];
[_urlMusic release];
[_sliderPlayer release];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
#pragma mark - AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
NSLog(@"Music play over");
[self onStop];
}
/* if an error occurs while decoding it will be reported to the delegate. */
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
NSLog(@"Music play occured error");
[self onStop];
}
@end
// 音频播放回调函数
void AudioFinishedCallBack(SystemSoundID idSound, void* data)
{
AudioServicesDisposeSystemSoundID(idSound);
}
媒体播放器(AVAudioPlayer,MPMoviePlayerViewController)
标签:avaudioplayer mpmovieplayerviewcon nsnotificationcenter 音乐播放器 媒体播放
原文地址:http://blog.csdn.net/arbboter/article/details/41958787