各位同学好,这篇文章的主要知识点在于音频的播放,使用MediaPlayer进行播放音乐,界面以简洁简单为主,废话不多说直接上代码吧。
- 这次由于是本地的文件所以没有权限需要。
/**
4. 当前类名 : MusicActivity
5. 包名 : com.jh.music.activitys
7. 类描述 : 简易音乐播放器
8. @author jiahui
*/
public class MusicActivity extends AppCompatActivity implements View.OnClickListener,
Runnable, ServiceConnection, SeekBar.OnSeekBarChangeListener{
private ImageView disc;
private ObjectAnimator discAnimation;//自定义指针和唱盘
private boolean isPlaying = true;//判断是否处于播放状态
//声明服务
private MediaService.MusicController mMusicController;
//使用方法:mMusicController.play();播放 mMusicController.pause();暂停
private boolean running;
private TextSwitcher mSwitcher;
private SeekBar mSeekBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music);
//滑动条部分
mSeekBar = (SeekBar) findViewById(R.id.music_seek_bar);
mSeekBar.setOnSeekBarChangeListener(this);
mSwitcher = (TextSwitcher) findViewById(R.id.text_switcher);
mSwitcher.setInAnimation(this, android.R.anim.fade_in);
mSwitcher.setOutAnimation(this, android.R.anim.fade_out);
Intent intent = new Intent(this, MediaService.class);
//增加StartService,来增加后台播放功能
startService(intent);
// 绑定服务,使用context来绑定
// 那个界面需要绑定 就用哪个 Activity
// 参数1:Intent 代表需要绑定哪一个Service
// 参数2:ServiceConnection 回调接口,可以接收到Service连接成功和断开的回调,成功就可以取到对象。
// 绑定服务 参数2就是服务和指定的对象绑定在一起
bindService(intent, this, BIND_AUTO_CREATE);
//指针和唱片部分
initViews();//定义背景图
setAnimations();
}
private void initViews() {
Button playingPre = (Button) findViewById(R.id.playing_pre);
Button playingPlay = (Button) findViewById(R.id.playing_play);
Button playingNext = (Button) findViewById(R.id.playing_next);
disc = (ImageView) findViewById(R.id.disc);
playingPre.setOnClickListener(this);
playingPlay.setOnClickListener(this);
playingNext.setOnClickListener(this);
}
//动画设置
private void setAnimations() {
discAnimation = ObjectAnimator.ofFloat(disc, "rotation", 0, 360);
discAnimation.setDuration(20000);
discAnimation.setInterpolator(new LinearInterpolator());
discAnimation.setRepeatCount(ValueAnimator.INFINITE);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.playing_pre://前一曲
if (discAnimation != null) {
discAnimation.end();
playing();
}
break;
case R.id.playing_play://播放中
if (isPlaying){
playing();
}else {
if (discAnimation != null && discAnimation.isRunning()) {
discAnimation.cancel();
mMusicController.pause();
float valueAvatar = (float) discAnimation.getAnimatedValue();
discAnimation.setFloatValues(valueAvatar, 360f + valueAvatar);
}
isPlaying = true;
}
break;
case R.id.playing_next://下一曲
if (discAnimation != null) {
discAnimation.end();
playing();
}
break;
default:
break;
}
}
//播放:1、播放音乐 2、动画旋转 3、暂停图片切换为播放按钮图片
private void playing(){
discAnimation.start();
mMusicController.play();//播放
isPlaying = false;
}
//===================================播放歌曲服务开启、停止、结束===============================
@Override
protected void onStart() {
super.onStart();
Thread thread = new Thread(this);
thread.start();
}
@Override
protected void onStop() {
running = false;
super.onStop();
}
@Override
protected void onDestroy() {
// 解除绑定
unbindService(this);
super.onDestroy();
}
//---------------------播放到当前音乐的滑动条及时间设置--------------------------
@Override
public void run() {
running = true;
try {
while (running) {
if (mMusicController != null) {
long musicDuration = mMusicController.getMusicDuration();
final long position = mMusicController.getPosition();
final Date dateTotal = new Date(musicDuration);
final SimpleDateFormat sb = new SimpleDateFormat("mm:ss");
mSeekBar.setMax((int) musicDuration);
mSeekBar.setProgress((int) position);
mSwitcher.post(
new Runnable() {
@Override
public void run() {
Date date = new Date(position);
String time = sb.format(date) + "/" + sb.format(dateTotal);
mSwitcher.setCurrentText(time);
}
}
);
}
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//-----------------------------
//服务绑定与解除绑定的回调
/**
* 当服务与当前绑定对象,绑定成功,服务onBind方法调用并且返回之后
* 回调给这个方法
*
* @param name
* @param service IBinder 就是服务 onBind 返回的对象
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMusicController = ((MediaService.MusicController) service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mMusicController = null;
}
public void btnStopService(View view) {
Intent intent = new Intent(this, MediaService.class);
stopService(intent);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mMusicController.setPosition(seekBar.getProgress());
}
}
/**
* 当前类名 : MediaService
* 包名 : com.jh.music.services
* 类描述 : 播放音乐的Service
* @author jiahui
*/
public class MediaService extends Service {
private MediaPlayer mPlayer;
/* 绑定服务的实现流程:
* 1.服务 onCreate, onBind, onDestroy 方法
* 2.onBind 方法需要返回一个 IBinder 对象
* 3.如果 Activity 绑定,Activity 就可以取到 IBinder 对象,可以直接调用对象的方法
*/
// 相同应用内部不同组件绑定,可以使用内部类以及Binder对象来返回。
public class MusicController extends Binder {
public void play() {
mPlayer.start();//开启音乐
}
public void pause() {
mPlayer.pause();//暂停音乐
}
public long getMusicDuration() {
return mPlayer.getDuration();//获取文件的总长度
}
public long getPosition() {
return mPlayer.getCurrentPosition();//获取当前播放进度
}
public void setPosition (int position) {
mPlayer.seekTo(position);//重新设定播放进度
}
}
/**
* 当绑定服务的时候,自动回调这个方法
* 返回的对象可以直接操作Service内部的内容
*/
@Override
public IBinder onBind(Intent intent) {
return new MusicController();
}
@Override
public void onCreate() {
super.onCreate();
mPlayer = MediaPlayer.create(this, R.raw.music_rose);
}
/**
* 任意一次unbindService()方法,都会触发这个方法
* 用于释放一些绑定时使用的资源
*/
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
if (mPlayer.isPlaying()) {
mPlayer.stop();
}
mPlayer.release();
mPlayer = null;
super.onDestroy();
}
}
按照我的顺序往项目中拷贝就可以运行,运行不起来找我,ok到此结束,通篇没有废话,因为我在代码中都添加了注释,对了文章尾部要提供Api,不好意思差点忘了,运行效果就不加了,跟布局相同
MediaPlayer 常用方法介绍
方法:create(Context context, Uri uri)
解释:静态方法,通过Uri创建一个多媒体播放器。
方法:create(Context context, int resid)
解释:静态方法,通过资源ID创建一个多媒体播放器
方法:create(Context context, Uri uri, SurfaceHolder holder)
解释:静态方法,通过Uri和指定 SurfaceHolder 【抽象类】 创建一个多媒体播放器
方法: getCurrentPosition()
解释:返回 Int, 得到当前播放位置
方法: getDuration()
解释:返回 Int,得到文件的时间
方法:getVideoHeight()
解释:返回 Int ,得到视频的高度
方法:getVideoWidth()
解释:返回 Int,得到视频的宽度
方法:isLooping()
解释:返回 boolean ,是否循环播放
方法:isPlaying()
解释:返回 boolean,是否正在播放
方法:pause()
解释:无返回值 ,暂停
方法:prepare()
解释:无返回值,准备同步
方法:prepareAsync()
解释:无返回值,准备异步
方法:release()
解释:无返回值,释放 MediaPlayer 对象
方法:reset()
解释:无返回值,重置 MediaPlayer 对象
方法:seekTo(int msec)
解释:无返回值,指定播放的位置(以毫秒为单位的时间)
方法:setAudioStreamType(int streamtype)
解释:无返回值,指定流媒体的类型
方法:setDataSource(String path)
解释:无返回值,设置多媒体数据来源【根据 路径】
方法:setDataSource(FileDescriptor fd, long offset, long length)
解释:无返回值,设置多媒体数据来源【根据 FileDescriptor】
方法:setDataSource(FileDescriptor fd)
解释:无返回值,设置多媒体数据来源【根据 FileDescriptor】
方法:setDataSource(Context context, Uri uri)
解释:无返回值,设置多媒体数据来源【根据 Uri】
方法:setDisplay(SurfaceHolder sh)
解释:无返回值,设置用 SurfaceHolder 来显示多媒体
方法:setLooping(boolean looping)
解释:无返回值,设置是否循环播放
事件:setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)
解释:监听事件,网络流媒体的缓冲监听
事件:setOnCompletionListener(MediaPlayer.OnCompletionListener listener)
解释:监听事件,网络流媒体播放结束监听
事件:setOnErrorListener(MediaPlayer.OnErrorListener listener)
解释:监听事件,设置错误信息监听
事件:setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)
解释:监听事件,视频尺寸监听
方法:setScreenOnWhilePlaying(boolean screenOn)
解释:无返回值,设置是否使用 SurfaceHolder 显示
方法:setVolume(float leftVolume, float rightVolume)
解释:无返回值,设置音量
方法:start()
解释:无返回值,开始播放
方法:stop()
解释:无返回值,停止播放