本地音乐播放器(二)——界面和服务的初始化

一. 主界面的初始化(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);
    }

第一个方法是用来发送给服务,告诉它界面当前执行的是什么动作,如:播放暂停,上一首,下一首,切换模式等。第二个方法除了告诉服务当前的动作外,还要额外带一些数据的广播。

  1. 服务封装的发送广播的方法:
    /**
     * 更新界面的数据
     */
    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中,此篇就介绍到这里,这些所有的铺垫做完后,下一篇正式开始现实逻辑业务,界面和服务项目通信传递数据并处理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值