本地音乐播放器——界面和服务的初始化
Posted xingxing_yan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了本地音乐播放器——界面和服务的初始化相关的知识,希望对你有一定的参考价值。
一. 主界面的初始化(MainActivity.java):
开始前先说一下,项目中所有的Activity都是继承BaseActivity,此类是一个abstract,里边有三个虚方法,子类继承需要实现:
/**
* 初始化布局
*/
protected abstract void setLayout();
/**
* 初始化控件
*/
protected abstract void initView();
/**
* 初始化监听器
*/
protected abstract void setListener();
setLayout比较简单,主要就是设置一下此界面要显示的布局,而setListener中只是注册按钮的监听,所以我们主要看MainActivity中的InitView方法:
@Override
protected void initView()
mMusicImage = (XCRoundImageView) findViewById(R.id.main_music_image);
mPlayedTime = (TextView) findViewById(R.id.main_music_play_time);
mTotalTime = (TextView) findViewById(R.id.main_music_total_time);
mMusicSeekBar = (SeekBar) findViewById(R.id.main_music_seekbar);
mPlayMode = (ImageView) findViewById(R.id.main_play_mode);
mMusicNext = (ImageView) findViewById(R.id.main_music_next);
mMusicPrev = (ImageView) findViewById(R.id.main_music_previous);
mMusicPlay = (ImageView) findViewById(R.id.main_music_play);
mTvMusicName = (TextView) findViewById(R.id.main_music_name);
mTvMusicList = (TextView) findViewById(R.id.main_music_list);
mTvMusicName.setText("未知");
initAnimation();
//注册广播接收器
mMusicReceiver = new MusicReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Contants.ACTIVITY_RECEIVER_ACTION);
registerReceiver(mMusicReceiver, filter);
if (!Utils.isMusicServerRunning(this))
startMusicServer(); //启动服务
else
Intent intent = getIntent();
if (intent.hasExtra(Contants.MUSIC_POS)) //从歌曲列表进入此页面
int position = intent.getIntExtra(Contants.MUSIC_POS, -1);
sendBroadcastToServer(Contants.REPLAY, position);
else //如果服务在运行,则发广播让服务更新界面
sendBroadcastToServer(Contants.UPDATE_PLAY_ACTIVITY, -1);
首先我们初始化了所有的控件,然后初始化了一个动画,此动画主要是要来控制mMusicImage 的旋转,这个后边会介绍。然后是注册广播,这没什么说的,记得一个要给filter添加一个action,否则activity就不知道广播要发给谁了。接下来才是重要的,先判断MusicServer是不是在运行,如果没有就启动服务,否则我们需要判断是不是从音乐列表界面跳转到此界面中的,如果是,则将传过来的position的信息发给服务,告诉它需要播放这首音乐。最后,如果是从桌面启动的应用,则进入主界面后给服务发送广播来更新当前界面的信息。
二. 初始化服务(MusicServer):
先来看onCreate方法:
@Override
public void onCreate()
super.onCreate();
//申请电源锁,已在锁屏后,手机不清理后台服务(然并卵)
acquireWakeLock();
//注册接收器
mReceiver = new ServiceReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Contants.SERVER_RECEIVER_ACTION);
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(mReceiver, filter);
mBundle = new Bundle();
//从本地读取之前保存的音乐,模式和播放的位置(初始化界面用)
mMusicPosition = MusicInfo.getMusicPosition(this);
mMusicMode = MusicInfo.getMusicMode(this);
mMusicPlayPos = MusicInfo.getMusicPlayPosition(this);
//获取音乐列表和当前的音乐对象
mMusicFiles = Utils.getMusicFile(this);
if (mMusicFiles != null &&
(mMusicPosition >= 0 && mMusicPosition < mMusicFiles.size()))
mPlayingMusic = mMusicFiles.get(mMusicPosition);
Uri uri = Uri.parse(mPlayingMusic.getUrl());
mMediaPlayer = MediaPlayer.create(this, uri);
mTimer = new Timer();
mTimer.schedule(new UpdateProgressTask(), 0);
mAmanager = (AudioManager) getApplicationContext().
getSystemService(Context.AUDIO_SERVICE);
mListener = new MyOnAudioFocusChangeListener();
setListener();
逐个分析:
1. 申请电源锁,这个方法主要是获取手机锁屏后的一个锁,防止手机锁屏后会清掉我们的服务(有些手机锁屏后会自动清理应用)。不过试过后好像没有什么作用,其实一般手机中设置手机锁屏后不清理哪些应用,所以可以忽略。
2. 注册接收器,在接收器中接收来自界面的广播,并做相应的处理。
3. 读取本地保存信息:在我们每次启动服务时,服务都需要知道之前我们播放的音乐的一下信息,用来初始化界面,所以我们需要在本地保存音乐在列表中的位置mMusicPosition, 播放模式mMusicMode,以及音乐之前播放的位置mMusicPlayPos。
4. 获取音乐列表, MusicServer中需要存储SD卡中所有的音频文件,然后根据mMusicPosition的值来初始化当前音乐mPlayingMusic,mPlayingMusic中有当前音乐的所有信息,这样从音乐列表选择播放某个音乐时,只需要传递position就可以了。
5. 初始化MediaPlayer,根据当前音乐的URL来初始化mMediaPlayer。
6. 定时器:这个定时器主要是用来改变音乐播放进度的,后边会详细解说。
7. 获取音频管理器mAmanager,后边在监听耳机拔出的时候会用到,然后初始化耳机的监听器
8. 设置监听,主要是音乐播放完成后的监听
当启动服务时,服务还需要主动发送一个广播时初始化界面,我们在onStartCommand中做这件事:
@Override
public int onStartCommand(Intent intent, int flags, int startId)
sendBroadcastToActivity();
return super.onStartCommand(intent, flags, startId);
以上就是主界面和服务的所有初始化操作,接下来,就是服务和界面之间通过广播来进行逻辑业务的实现。
三. 对服务和界面发送广播一些数据的封装:
1.MainActivity中封装的发送广播的方法:
/**
* 给服务发送广播
* @param state
*
*/
private void sendBroadcastToServer(int state)
Intent intent = new Intent();
intent.setAction(Contants.SERVER_RECEIVER_ACTION);
intent.putExtra(Contants.SERVER_SIGNAL, state);
sendBroadcast(intent);
private void sendBroadcastToServer(int state, Bundle bundle)
Intent intent = new Intent();
intent.setAction(Contants.SERVER_RECEIVER_ACTION);
intent.putExtra(Contants.SERVER_SIGNAL, state);
if (bundle != null)
intent.putExtras(bundle);
sendBroadcast(intent);
第一个方法是用来发送给服务,告诉它界面当前执行的是什么动作,如:播放暂停,上一首,下一首,切换模式等。第二个方法除了告诉服务当前的动作外,还要额外带一些数据的广播。
- 服务封装的发送广播的方法:
/**
* 更新界面的数据
*/
private void setUpdateActivityParam()
mBundle.clear();
mBundle.putInt(Contants.ACTIVITY_SIGNAL, Contants.UPDATE_PLAY_ACTIVITY);
mBundle.putInt(Contants.MUSIC_STATE, mMusicState);
mBundle.putInt(Contants.MUSIC_MODE, mMusicMode);
mBundle.putInt(Contants.MUSIC_PLAY_POS, mMusicPlayPos);
mBundle.putSerializable(Contants.CURRENT_MUSIC, mPlayingMusic);
/**
* 向界面发送广播
*/
private void sendBroadcastToActivity()
setUpdateActivityParam();
Intent intent = new Intent();
intent.setAction(Contants.ACTIVITY_RECEIVER_ACTION);
if (mBundle != null)
intent.putExtras(mBundle);
sendBroadcast(intent);
setUpdateActivityParam方法封装更新界面所需的所有数据(当前音乐状态,当前播放模式,当前播放位置,当前播放的音乐),就是说,不论界面执行的时那个动作,这些返回的数据是一致的,方便界面统一做处理。而sendBroadcastToActivity则封装了发送给界面的广播。
所有用到的常量都封装在Contants.java中,此篇就介绍到这里,这些所有的铺垫做完后,下一篇正式开始现实逻辑业务,界面和服务项目通信传递数据并处理。
以上是关于本地音乐播放器——界面和服务的初始化的主要内容,如果未能解决你的问题,请参考以下文章