Android-音频播放(一)

最近学习了关于Android 的音频播放,以及系统中各应用之间对于音频播放的资源竞争处理。如何处理应用处于播放的状态下,其他的音频如何影响当前的状态。
例如:当手机播放一个音乐,同时来了一个电话,这时音乐停止,当通话结束时再继续播放。

如何创建一个播放音频

注意:Media Player 只介绍最基础的,其他的方法后期遇到在进行详解。

Media Player 类:媒体播放器类可用于控制播放的音频/视频文件和流。
Media Player的生命周期图

创建一个音频的语法:

1
MediaPlayer mMediaPlayer = MediaPlayer.create(Context context, int resid);

第一个参数:播放的位置
第二个参数:音频的资源ID(一般方法哦 raw 文件夹中)

其中的方法我们只介绍常用的,以后遇到在进行总结归纳

//播放开始后暂停,再播放从上次停止的位置继续
start()进行播放
pause()暂停

//如果括号为0,音频回到最初的位置
seekTo() 指定的时间位置
reset()重置

//停止后 只有先prepare()才能 start()
stop()停止
prepare()准备

//当播放完后需要释放资源
release()释放资源

上述其他方法可以查看生命周期图

应用播放机制

要想播放音频,先要获取 Audio Focus,可以理解为只有获取到音频焦点的才可以播放,虽然 Android 2.2 之后添加了 Audio Focus,来处理系统之间音频的混乱。如果有程序在它失去AudioFocus的时候仍然在使用Audio,AudioFocus拿它也没办法,用户可能安装没遵守这种机制的程序,或者版本太老还没引入这种机制的程序,这最终会导致很差的用户体验。

  1. 如何获取 Audio Focus?

利用 AudioManager 来管理AudioFocus,先要实例化AudioManager

1
AudioManager mAudioManager=(AudioManager)getSystemService(this.AUDIO_SERVICE);

mAudioManager提供两个方法 :

requestAudioFocus 获取焦点

1
int requestAudioFocus (AudioManager.OnAudioFocusChangeListener, int streamType, int durationHint);

参数:

  1. 焦点状态改变监听器
  2. 输入流类型
    • STREAM_MUSIC 一般的音频其他的可以查看官方文档)
  3. 持续时间

请求焦点会有两个结果
1 AUDIOFOCUS_REQUEST_GRANTED 请求焦点成功
2 AUDIOFICUS_REQUEST_FAILED 请求焦点失败


abandonAudioFocus 释放焦点

1
int abandonAudioFocus (AudioManager.OnAudioFocusChangeListener)
焦点状态改变监听器

通过一个 onAudioFocusChangeLiestener 方法回调来获得 Audiofocus 发生更改 后 的通知
监听设备更改 以便做出响应 onAudioFocusChangeLiestener 是一种接口 包含一个必须实施的onAudioFocusChange 抽象类(如果获得焦点 应该做什么,失去后应该做什么

onAudioFocusChange:
四个参数:

  1. AUDIOFOCUS_GAIN
  2. AUDIOFOCUS_LOSS
  3. AUDIOFOCUS_LOSS_TRANSIENT
  4. AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK

不懂的可以点看连接详细理解。

实战演练

实现当失去焦点时,暂停,等恢复获得焦点后,继续播放

下面是通过 ArrayList 一个数组列表(List+ArrayAdapter实现),看不懂没关系,主要理解当点击时,先获取 AudioFocus 状态,根据焦点状态进行判断

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
public class NumbersActivity extends AppCompatActivity {
//定义一个音频管理的对象
private AudioManager mAudioManager;
//创建一个监听音频聚焦的监听器
AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener =
new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int i) {
//判断当状态 暂时失去音频焦点 暂停并并重置
if(i==AudioManager.AUDIOFOCUS_LOSS_TRANSIENT||
i==AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK){
mediaPlayer.pause();
mediaPlayer.seekTo(0);
}else
//判断当状态获取音频焦点时应该播放
if(i==AudioManager.AUDIOFOCUS_GAIN){
mediaPlayer.start();
}else
//当前状态 永远失去焦点的时候 释放资源
if(i==AudioManager.AUDIOFOCUS_LOSS){
releaseMediaPlayer();
}
}
};
private MediaPlayer mediaPlayer;
//???有必要吗?
private MediaPlayer.OnCompletionListener mCompletionListener = new
MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
releaseMediaPlayer();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.word_list);
//获取AudioManager
mAudioManager = (AudioManager) getSystemService(this.AUDIO_SERVICE);
//自定义的数组列表 类型是Word类的数据
final ArrayList<Word> words = new ArrayList<Word>();
words.add(new Word("one", "lutti", R.drawable.number_one,
//自定义的一个适配器,继承以前的数组适配器
WordAdapter itemsAdapter = new WordAdapter(this, words, R.color.category_numbers);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(itemsAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Word word = words.get(i);
//request 获取Audio Focus
int result=mAudioManager.requestAudioFocus(mAudioFocusChangeListener
, AudioManager.STREAM_MUSIC
, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
//成功的焦点更改请求
if(result==AudioManager.AUDIOFOCUS_REQUEST_GRANTED){
//创建一个MediaPlayer
mediaPlayer = MediaPlayer.
create(NumbersActivity.this, word.getMusicResource());
//开始播放
mediaPlayer.start();
//
mediaPlayer.setOnCompletionListener(mCompletionListener);
}
}
});
}
@Override
protected void onStop() {
super.onStop();
releaseMediaPlayer();
}
// 自定义的一个释放资源的类
private void releaseMediaPlayer() {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
//失去焦点
mAudioManager.abandonAudioFocus(mAudioFocusChangeListener);
}
}
}
(*^▽^*)