前言:之前做项目涉及到一个功能是播放音频,考虑到其逻辑比较简单,便采用安卓自带的MediaPlayer实现。先了解一下需求,接收三个参数分别是标题、图片地址和音频url,支持播放、暂停、重放以及拖动控制条。
要实现前言中涉及到的几个功能,我们需要先熟悉一下MediaPlayer提供的几个方法:
1、setDataSource,设置数据源,也就是前言中提到的音频url
2、prepare、start,分别是准备与开始播放
3、isPlaying、pause、stop、release,分别是是否正在播放、暂停、停止、释放
4、getCurrentPosition、seekTo,获取当前播放位置、跳到某位置开始播放
基本这次需求就涉及到上面几个方法,接下来开始实现该需求:
1、界面设计
从需求可以看出界面不需要太复杂,主要由图片、进度条、暂停/播放按钮、重放按钮以及标题几部分组成,直接贴代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/relative"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/back"
android:layout_width="@dimen/dp_45"
android:layout_height="@dimen/dp_60"
android:padding="@dimen/dp_10"
android:src="@mipmap/back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_60"
android:layout_centerHorizontal="true"
android:gravity="center"
android:singleLine="true"
android:text="标题"
android:textColor="@color/black_font"
android:textSize="@dimen/text_16_sp" />
</RelativeLayout>
<TextView
android:id="@+id/data"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_alignParentBottom="true"
android:layout_marginBottom="@dimen/dp_30"
android:textColor="@color/black_font"
android:layout_marginLeft="@dimen/dp_30"
android:visibility="invisible"
android:gravity="center_vertical"
android:text="正在缓冲" />
<LinearLayout
android:id="@+id/linearButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/data"
android:layout_marginLeft="@dimen/dp_30"
android:layout_marginRight="@dimen/dp_30"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/play_pause"
android:layout_width="@dimen/dp_60"
android:layout_height="@dimen/dp_60"
android:padding="@dimen/dp_15"
android:src="@mipmap/stop_play_music" />
<ImageView
android:id="@+id/reset"
android:layout_width="@dimen/dp_60"
android:layout_height="@dimen/dp_60"
android:padding="@dimen/dp_15"
android:src="@mipmap/resetting" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_10" />
</LinearLayout>
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_500"
android:layout_above="@id/linearButton"
android:layout_below="@id/relative"
android:layout_centerHorizontal="true"
android:layout_margin="@dimen/dp_30"
android:scaleType="centerCrop"
android:src="@mipmap/vp1" />
</RelativeLayout>
2、逻辑实现
public class EnglistDetailedActivity extends BaseActivity {
@BindView(R.id.back)
ImageView back;
@BindView(R.id.title)
TextView title;
@BindView(R.id.iv)
ImageView iv;
@BindView(R.id.data)
TextView data;
@BindView(R.id.relative)
RelativeLayout relative;
@BindView(R.id.play_pause)
ImageView playPause;
@BindView(R.id.reset)
ImageView reset;
@BindView(R.id.seekbar)
SeekBar seekbar;
@BindView(R.id.linearButton)
LinearLayout linearButton;
private String title1;
private String picture;
private String path;
private MediaPlayer player = null;
private boolean ifplay = false;
private boolean iffirst = false;
private Timer mTimer;
private TimerTask mTimerTask;
private boolean isChanging = false;//互斥变量,防止定时器与SeekBar拖动时进度冲突
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_englist_detailed);
ButterKnife.bind(this);
Intent intent = getIntent();
path = intent.getStringExtra("path");
picture = intent.getStringExtra("picture");
title1 = intent.getStringExtra("title");
title.setText(title1);
player = new MediaPlayer();
playPause.setOnClickListener(new MyClick());
reset.setOnClickListener(new MyClick());
seekbar.setOnSeekBarChangeListener(new MySeekbar());
GlideLoadUtils.getInstance().glideLoad(this, picture, iv, R.color.default_bg);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (player != null) {
try {
if (player.isPlaying()) {
player.stop();
player.release();
}
} catch (IllegalStateException e) {
}
}
if (mTimer != null || mTimerTask != null) {
mTimer.purge();
mTimerTask.cancel();
}
if (seekbar != null) {
seekbar = null;
}
finish();
}
});
}
class MyClick implements View.OnClickListener {
public void onClick(View v) {
switch (v.getId()) {
case R.id.play_pause:
if (player != null && !ifplay) {
// data.setVisibility(View.VISIBLE);
playPause.setImageResource(R.mipmap.start_play_music);
if (!iffirst) {
player.reset();
try {
player.setDataSource(path);
player.prepare();// 准备
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
seekbar.setMax(player.getDuration());//设置进度条
//----------定时器记录播放进度---------//
mTimer = new Timer();
mTimerTask = new TimerTask() {
@Override
public void run() {
if (isChanging == true) {
return;
}
try {
if (player.getCurrentPosition()>0){
}
seekbar.setProgress(player.getCurrentPosition());
}catch (IllegalStateException e){
e.printStackTrace();
}
}
};
mTimer.schedule(mTimerTask, 0, 10);
iffirst = true;
}
player.start();// 开始
ifplay = true;
} else if (ifplay) {
playPause.setImageResource(R.mipmap.stop_play_music);
// data.setVisibility(View.INVISIBLE);
player.pause();
ifplay = false;
}
break;
case R.id.reset:
if (ifplay) {
// data.setVisibility(View.INVISIBLE);
player.seekTo(0);
} else {
// data.setVisibility(View.VISIBLE);
player.reset();
try {
player.setDataSource(path);
player.prepare();// 准备
player.start();// 开始
// data.setVisibility(View.INVISIBLE);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
break;
}
// }
}
}
//进度条处理
class MySeekbar implements SeekBar.OnSeekBarChangeListener {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
public void onStartTrackingTouch(SeekBar seekBar) {
isChanging = true;
}
public void onStopTrackingTouch(SeekBar seekBar) {
player.seekTo(seekbar.getProgress());
isChanging = false;
}
}
protected void onDestroy() {
if (player != null) {
try {
if (player.isPlaying()) {
player.stop();
player.release();
}
} catch (
IllegalStateException e) {
}
}
super.onDestroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (player != null) {
try {
if (player.isPlaying()) {
player.stop();
player.release();
}
} catch (IllegalStateException e) {
}
}
if (mTimer != null || mTimerTask != null) {
mTimer.purge();
mTimerTask.cancel();
}
if (seekbar != null) {
seekbar = null;
}
finish();
}
return super.onKeyDown(keyCode, event);
}
protected void onPause() {
if (player != null) {
try {
if (player.isPlaying()) {
player.pause();
}
} catch (IllegalStateException e) {
}
}
super.onPause();
}
protected void onResume() {
// data.setVisibility(View.VISIBLE);
if (player != null) {
try {
if (!player.isPlaying()) {
player.start();
// data.setVisibility(View.INVISIBLE);
}
} catch (IllegalStateException e) {
}
}
super.onResume();
}
}
3、效果图