手把手教你做音乐播放器(八)桌面小工具(下)(完)

8.4 MusicService的改造

8.4.1 App widget触发MusicService

App widget的按钮被点击后,会触发隐式定义的Intent发送给MusicService。例如当下一首按钮被点击后,携带action-MusicService.ACTION_PLAY_MUSIC_NEXT的Intent将触发MusicServiceonStartCommand()函数。

我们可以在onStartCommand()函数当中接收到App widget要求的操作命令,进行相应的处理。

public class MusicService extends Service {

    public static final String ACTION_PLAY_MUSIC_PRE = "com.anddle.anddlemusic.playpre";
    public static final String ACTION_PLAY_MUSIC_NEXT = "com.anddle.anddlemusic.playnext";
    public static final String ACTION_PLAY_MUSIC_TOGGLE = "com.anddle.anddlemusic.playtoggle";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if(intent != null) {
            //获取App widget发来的操作命令
            String action = intent.getAction();
            if (action != null) {
                if (ACTION_PLAY_MUSIC_PRE.equals(action)) {
                    //播放前一首音乐
                    playPreInner();
                } else if (ACTION_PLAY_MUSIC_NEXT.equals(action)) {
                    //播放下一首音乐
                    playNextInner();
                } else if (ACTION_PLAY_MUSIC_TOGGLE.equals(action)) {
                    //根据当前播放的状态暂停或继续播放音乐
                    if (isPlayingInner()) {
                        pauseInner();
                    } else {
                        playInner();
                    }
                }
            }
        }

        return super.onStartCommand(intent, flags, startId);
    }

}

8.4.2 MusicService更新App widget

MusicService自身的播放状态发生变化的时候,比如开始播放、暂停播放,就需要更新App widget的显示,

public class MusicService extends Service {
    ......
    //将音乐的播放信息更新到App widget中
    private void updateAppWidget(MusicItem item) {
        if (item != null) {
            //创建音乐封面
            if(item.thumb == null) {
                ContentResolver res = getContentResolver();
                item.thumb = Utils.createThumbFromUir(res, item.albumUri);
            }
            //调用App widget提供的更新接口开始更新
            AnddleMusicAppWidget.performUpdates(MusicService.this, item.name, isPlayingInner(), item.thumb);
        }
    }

    private void pauseInner() {
        ......
        //音乐暂停时更新到App widget
        updateAppWidget(mCurrentMusicItem);
    }

    private void playMusicItem(MusicItem item, boolean reload) {
       ......
       //音乐播放时更新到App widget
       updateAppWidget(mCurrentMusicItem);
    }

}

8.5 App widget的初始化

当App widget被添加到桌面或者系统启动后让App widget在桌面显示出来,需要显示当前的播放信息。

手把手教你做音乐播放器(八)桌面小工具(下)(完)_第1张图片

假如MusicService已经在后台运行着,那么App widget只需要在onUpdate()的时候通知MusicService,让MusicService调用接口更新一下自己。

假如是刚刚开机,MusicService还没有运行起来,那么App widget需要让MusicService`先运行起来,再调用接口更新一下自己。

8.5.1 MusicService已经启动

  1. AnddleMusicAppWidgetonUpdate()中,向已经启动的MusicService发送一个广播,告诉它App widget需要被更新一下,

    public class MusicService extends Service {
        ......
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    
            sAppWidgetIds = appWidgetIds;
            //使用默认的参数更新App widget
            performUpdates(context, context.getString(R.string.no_song), false, null);
    
            //发送广播给MusicService,让它调用接口,更新App widget
            Intent updateIntent = new Intent(MusicService.ACTION_PLAY_MUSIC_UPDATE);
            context.sendBroadcast(updateIntent);
        }
    }
  2. MusicService在启动之后,要随时监听App widget发出的MusicService.ACTION_PLAY_MUSIC_UPDATE广播,一旦收到这个广播,就要响应去跟新App widget界面,

    public class MusicService extends Service {
        ......
        //定义广播名称
        public static final String ACTION_PLAY_MUSIC_UPDATE = "com.anddle.anddlemusic.playupdate";
    
        //定义ACTION_PLAY_MUSIC_UPDATE广播的监听器
        private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
    
                String action = intent.getAction();
                if (ACTION_PLAY_MUSIC_UPDATE.equals(action)) {
                    //收到ACTION_PLAY_MUSIC_UPDATE广播,就更新App widget
                    updateAppWidget(mCurrentMusicItem);
                }
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
            ......
            //注册监听器,当收到ACTION_PLAY_MUSIC_UPDATE广播的时候,将触发mIntentReceiver的onReceive()方法被调用
            IntentFilter commandFilter = new IntentFilter();
            commandFilter.addAction(ACTION_PLAY_MUSIC_UPDATE);
            registerReceiver(mIntentReceiver, commandFilter);
            ......
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            ......
            //注销监听器,防止内存泄漏
            unregisterReceiver(mIntentReceiver);
            ......
        }
    
        ......
    }

8.5.2 MusicService没有启动

如果设备刚开机,而桌面又添加了音乐的App widget,那么就让App widget在被加载到桌面上的时候(onEnabled()被触发时)启动MusicService

public class AnddleMusicAppWidget extends AppWidgetProvider {

    ......
    @Override
    public void onEnabled(Context context) {

        Intent i = new Intent(context, MusicService.class);
        context.startService(i);
    }

}

之后更新App widget的流程就和MusicService已经启动了的流程一致了。

后记

经过前面几个章节,音乐播放器已经完成了。

手把手教你做音乐播放器(八)桌面小工具(下)(完)_第2张图片

我们可以多放一点音乐进去,用它实际的播放歌曲。虽然功能基本上开发完了,但是少不了测试的环节。就目前我们的开发水平而言,我们可以通过多使用,来寻找软件的Bug。如果遇到崩溃、或者使用时发现的设计不合理的地方,就根据自己的想法来修改。逐步的让音乐播放器变成一个稳定实用的应用。

在功能规划的时候,我们还省去了不少实用的功能,也许在下一版本的音乐播放器中,我们就可以添加上其中的部分功能了。

在经过了“安豆计算器” “视频播放器” “蓝牙聊天应用”和“音乐播放器”以后,我相信大家一定对安卓应用开发有了较为深刻的理解了。至此,大家已经入门了,恭喜恭喜。

/*******************************************************************/
* 版权声明
* 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。

*另外,我们还推出了Arduino智能硬件相关的教程,您可以在我们的网店跟我学Arduino编程中购买相关硬件。同时也感谢大家对我们这些码农的支持。

*最后再次感谢各位读者对安豆的支持,谢谢:)
/*******************************************************************/

你可能感兴趣的:(APP,音乐,widget)