服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - 实例讲解iOS音乐播放器DOUAudioStreamer用法

实例讲解iOS音乐播放器DOUAudioStreamer用法

2021-04-12 10:54huangyn IOS

本篇文章给大家通过实例讲解了iOS音乐播放器DOUAudioStreamer用法以及分享了实例代码,一起学习参考下吧。

好久没有写东西了,最近加班太严重,今天抽空把用到的音乐播放器douaudiostreamer整理一下,由于项目之前用的是avplayer,这个也可以,但是就是要先缓存一段时间再播放,老板看了之后要求,要变缓存变播放(有网时,点击播放按钮就立刻播放),怎么不早说!怎么不早说!怎么不早说!还能怎样?只能原谅他,继续敲代码。。。。。。(还是直接上代码吧)

一、导入三方库

?
1
pod 'douaudiostreamer'

或者githup下载地址:https://github.com/douban/douaudiostreamer

二、使用

1.从demo中获取nakplaybackindicatorview文件和musicindicator.h和musicindicator.m 文件,并导入头文件

?
1
//音乐播放<br>#import "douaudiostreamer.h"<br>#import "nakplaybackindicatorview.h"<br>#import "musicindicator.h"<br>#import "track.h"

如图:

实例讲解iOS音乐播放器DOUAudioStreamer用法

2.创建一个track类,用于音乐播放的url存放

实例讲解iOS音乐播放器DOUAudioStreamer用法

3.需要的界面.h中,添加douaudiostreamer,并用单利来初始化

?
1
2
+ (instancetype)sharedinstance ;
@property (nonatomic, strong) douaudiostreamer *streamer;

 

如图:

实例讲解iOS音乐播放器DOUAudioStreamer用法

在.m中实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}

 

播放按钮事件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#pragma mark ---音乐播放按钮
-(void)playmusicstart:(uibutton *)sender
{
  //通过按钮获取cell
  musiccollectionviewcell *musiccell = (musiccollectionviewcell *)[[sender superview] superview];
 if(_playfirst == 0){//_playfirst == 0首次播放,其他为暂停
  nsurl *url = [nsurl urlwithstring:httpimgurl(musiccell.model.musicurl)];
  _audiotrack.audiofileurl = url;
  @try {
   [self removestreamerobserver];
  } @catch(id anexception){
  }
  //在douaudiostreamer进行播放时,必须先置为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++;
 
}

 

对添加监听

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
- (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];
}
/// 播放器销毁
- (void)dealloc{
 if (_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)removestreamerobserver {
 
 [_streamer removeobserver:self forkeypath:@"status"];
 [_streamer removeobserver:self forkeypath:@"duration"];
 [_streamer removeobserver:self forkeypath:@"bufferingratio"];
}
- (void)observevalueforkeypath:(nsstring *)keypath ofobject:(id)object change:(nsdictionary *)change context:(void *)context {
 if (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;
 }
}

这样就能播放了。

锁屏时的音乐显示、拔出耳机后暂停播放、监听音频打断事件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
-(void)viewwillappear:(bool)animated
{
[super viewwillappear:animated];
//接受远程控制
[self becomefirstresponder];
[[uiapplication sharedapplication] beginreceivingremotecontrolevents];
}
//这个不能忘记了
-(bool)canbecomefirstresponder{
return yes;
}
- (void)viewdidload {
[super viewdidload];
//音乐播放器
[self initplayer];
}
#pragma mark =========================音乐播放==============================
//音乐播放器
-(void)initplayer
{
_audiotrack = [[track alloc] init];
avaudiosession *session = [avaudiosession sharedinstance];
[session setactive:yes error:nil];
[session setcategory:avaudiosessioncategoryplayback error:nil];
//让app支持接受远程控制事件
[[uiapplication sharedapplication] beginreceivingremotecontrolevents];
//添加通知,拔出耳机后暂停播放
[[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(routechange:) name:avaudiosessionroutechangenotification object:nil];
// 监听音频打断事件
[[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(audiosessionwasinterrupted:) name:avaudiosessioninterruptionnotification object:session];
}
// 监听音频打断事件
- (void)audiosessionwasinterrupted:(nsnotification *)notification
{
 //被打断时
if (avaudiosessioninterruptiontypebegan == [notification.userinfo[avaudiosessioninterruptiontypekey] intvalue])
{
 
[_streamer pause];
uibutton *btn = (uibutton *)[self.view viewwithtag:2000];
[btn setbackgroundimage:[uiimage imagenamed:@"music_stop_icon"] forstate:uicontrolstatenormal];
}
else if (avaudiosessioninterruptiontypeended == [notification.userinfo[avaudiosessioninterruptiontypekey] intvalue])
{
}
}
// 拔出耳机后暂停播放
-(void)routechange:(nsnotification *)notification{
nsdictionary *dic=notification.userinfo;
int changereason= [dic[avaudiosessionroutechangereasonkey] intvalue];
//等于avaudiosessionroutechangereasonolddeviceunavailable表示旧输出不可用
if (changereason==avaudiosessionroutechangereasonolddeviceunavailable) {
avaudiosessionroutedescription *routedescription=dic[avaudiosessionroutechangepreviousroutekey];
avaudiosessionportdescription *portdescription= [routedescription.outputs firstobject];
//原设备为耳机则暂停
if ([portdescription.porttype isequaltostring:@"headphones"]) {
[_streamer pause];
uibutton *btn = (uibutton *)[self.view viewwithtag:2000];
[btn setbackgroundimage:[uiimage imagenamed:@"music_stop_icon"] forstate:uicontrolstatenormal];
}
}
}
//锁屏时音乐显示(这个方法可以在点击播放时,调用传值)
- (void)setuplockscreeninfowithsing:(nsstring *)sign withsigner:(nsstring *)signer withimage:(uiimage *)image
{
// 1.获取锁屏中心
mpnowplayinginfocenter *playinginfocenter = [mpnowplayinginfocenter defaultcenter];
//初始化一个存放音乐信息的字典
nsmutabledictionary *playinginfodict = [nsmutabledictionary dictionary];
// 2、设置歌曲名
if (sign) {
[playinginfodict setobject:sign forkey:mpmediaitempropertyalbumtitle];
}
// 设置歌手名
if (signer) {
[playinginfodict setobject:signer forkey:mpmediaitempropertyartist];
}
// 3设置封面的图片
//uiimage *image = [self getmusicimagewithmusicid:self.currentmodel];
if (image) {
mpmediaitemartwork *artwork = [[mpmediaitemartwork alloc] initwithimage:image];
[playinginfodict setobject:artwork forkey:mpmediaitempropertyartwork];
}
// 4设置歌曲的总时长
//[playinginfodict setobject:self.currentmodel.detailduration forkey:mpmediaitempropertyplaybackduration];
//音乐信息赋值给获取锁屏中心的nowplayinginfo属性
playinginfocenter.nowplayinginfo = playinginfodict;
// 5.开启远程交互
[[uiapplication sharedapplication] beginreceivingremotecontrolevents];
}
//锁屏时操作
- (void)remotecontrolreceivedwithevent:(uievent *)receivedevent {
if (receivedevent.type == uieventtyperemotecontrol) {
uibutton *sender = (uibutton *)[self.view viewwithtag:2000];
switch (receivedevent.subtype) {//判断是否为远程控制
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;
}
}
}

整体图片:

实例讲解iOS音乐播放器DOUAudioStreamer用法

上图为未播放

实例讲解iOS音乐播放器DOUAudioStreamer用法

上图为播放中

实例讲解iOS音乐播放器DOUAudioStreamer用法

上图为锁屏时状态

应该没有什么要添加的了,暂时告一段落,有不足之处,可以在下方的留言区讨论,感谢对服务器之家的支持。

原文链接:https://my.oschina.net/huangyn/blog/1593368

延伸 · 阅读

精彩推荐
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17