MVP模式的音乐播放器
public class MainActivity extends BaseActivity implements IMusicListView{ View headerView; ListView listView; //数据源(不写了,直接用) MusicAdapter adapter;//适配器 ProgressDialog pd;//进度对话框 IMusicListPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); presenter = new MusicListPresenterImpl(this); initView(); } @Override protected void onResume() { super.onResume(); presenter.onResume();//设置HeaderView的标题 presenter.showMusicList();//显示音乐列表 } private void initView() { headerView = findViewById(R.id.headerview); listView = (ListView)findViewById(R.id.lv_main_musiclist); pd = ProgressDialog.show(this, "", "正在加载请稍候..."); listView.setOnItemClickListener(new OnItemClickListener() {
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent2 = new Intent(MainActivity.this,MusicService.class); startService(intent2); 启动服务 // 点击跳转 Intent intent = new Intent(MainActivity.this,PlayActivity.class); intent.putExtra("musics", (ArrayList<Music>)adapter.getMusics());歌曲列表 intent.putExtra("position", position); 传递点击的歌曲的位置 //startActivity(intent); presenter.jumpTo(MainActivity.this, intent); } }); }
@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; }
@Override public void setHeaderViewTitle(String title) { setHeaderTitle(headerView, title); }
@Override public void setHeaderViewImage(int resId, Position pos) { //空实现 }
@Override public void showMusicList(List<Music> musics) { //Log.d("TAG","音乐列表:"+musics.toString()); adapter = new MusicAdapter(this, musics); listView.setAdapter(adapter); }
@Override public void showLoadingProgress() { pd.show(); }
@Override public void dismissLoadingProgress() { pd.dismiss(); } }
|
|
public class PlayActivity extends BaseActivity implements IMusicPlayView{ int position; List<Music> musics; DiscView discView; View headerView; ImageButton ibPlay,ibNext,ibPrev; SeekBar sbProgress; ImageView ivFavo,ivDownload; TextView tvCurrent,tvDuration; //用来接收MusicService发送的广播 MyReceiver receiver; IMusicPlayPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_play); position = getIntent().getIntExtra("position", -1); 接收 musics = (List<Music>) getIntent().getSerializableExtra("musics"); //presenter赋值 presenter = new MusicPlayPresenterImpl(this, musics, position); //Log.d("TAG","position: "+position); //Log.d("TAG","musics: "+musics.toString()); initView(); setListeners(); discView.getCircleImageView()); } @Override protected void onResume() { super.onResume(); //注册广播接收器,用来接收MusicService发送的广播 receiver = new MyReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(Constant.ACTION_UPDATE_PROGRESS); filter.addAction(Constant.ACTION_UPDATE_MUSIC_PLAYING); registerReceiver(receiver, filter ); presenter.onResume(); } @Override protected void onPause() { //注销广播接收器 unregisterReceiver(receiver); super.onPause(); } private void setListeners() { ibPlay.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { presenter.play(); } }); ibNext.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { presenter.next(); } }); ibPrev.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { presenter.prev(); } }); ivDownload.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { presenter.showDownloadDialog(); } }); sbProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { seekBar的监听器 @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(fromUser){ presenter.seekTo(progress); } } }); }
private void initView() { headerView = findViewById(R.id.headerview); discView = (DiscView) findViewById(R.id.discview); ibPlay = (ImageButton) findViewById(R.id.btn_play_play); ibNext = (ImageButton) findViewById(R.id.btn_play_next); ibPrev = (ImageButton) findViewById(R.id.btn_play_prev); sbProgress = (SeekBar) findViewById(R.id.sb_play_progress); ivFavo = (ImageView) findViewById(R.id.iv_play_favo); ivDownload = (ImageView) findViewById(R.id.iv_play_download); tvCurrent = (TextView) findViewById(R.id.tv_play_current); tvDuration = (TextView) findViewById(R.id.tv_play_duration); }
@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.play, menu); return true; }
@Override public void setHeaderViewTitle(String title) { setHeaderTitle(headerView, title); }
@Override public void setHeaderViewImage(int resId, Position pos) { //setHeaderImage(headerView, resId, pos); if(pos==Position.LEFT){ setHeaderImage(headerView, resId, pos,new OnClickListener() { @Override public void onClick(View v) { //如果严格MVP,不能这么写 //需要利用Presenter层跳转 finish(); } }); }else{ setHeaderImage(headerView, resId, pos, null); } }
@Override public void play(int pos) { discView.startRotate(); 更改UI ImageLoader.loadImage(musics.get(pos).getAlbumpic(), discView.getCircleImageView()); ibPlay.setImageResource(R.drawable.pause); //向MusicService发送播放音乐的广播 Intent intent = new Intent(Constant.ACTION_PLAY_MUSIC); //把要播放的音乐的路径作为广播Intent的一部分 String url = musics.get(pos).getMusicpath(); intent.putExtra("url",url); sendBroadcast(intent); }
@Override public void pause(int pos) { discView.stopRotate(); 更改UI ibPlay.setImageResource(R.drawable.play); //向MusicService发送暂停音乐的广播 Intent intent = new Intent(Constant.ACTION_PAUSE_MUSIC); //???要不要传url??? sendBroadcast(intent); }
@Override public void updateProgress(int current, int duration) { tvCurrent.setText(new SimpleDateFormat("mm:ss").format(current)); tvDuration.setText(new SimpleDateFormat("mm:ss").format(duration)); sbProgress.setProgress((current*100)/duration);更新UI }
@Override public void seekTo(int progress) { String duration = tvDuration.getText().toString();//05:07 try { Date date = new SimpleDateFormat("mm:ss").parse(duration); long current = (date.getTime()*progress)/100; tvCurrent.setText(new SimpleDateFormat("mm:ss").format(current)); //向MusicService发送快进音乐的广播 Intent intent = new Intent(Constant.ACTION_SEEKTO_MUSIC); intent.putExtra("progress", progress); sendBroadcast(intent); } catch (ParseException e) { e.printStackTrace(); } }
@Override public void showDownloadDialog(final int pos) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setIcon(android.R.drawable.ic_menu_info_details); builder.setTitle("下载通知"); builder.setMessage("确实要下载"+musics.get(pos).getName()+"嘛?"); builder.setNegativeButton("再想想", null); builder.setPositiveButton("去下载", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String url = musics.get(pos).getMusicpath(); presenter.startDownload(url); } }); builder.create().show(); } private class MyReceiver extends BroadcastReceiver{
@Override public void onReceive(Context context, Intent intent) { //获取MusicService发送的广播ACTION //根据不同的ACTION执行不同的行为 String action = intent.getAction(); if(Constant.ACTION_UPDATE_PROGRESS.equals(action)){ //更新sbProgress int current = intent.getIntExtra("current", -1); int duration = intent.getIntExtra("duration", -1); presenter.updateProgress(current, duration); } if(Constant.ACTION_UPDATE_MUSIC_PLAYING.equals(action)){ //播放下一曲 presenter.next(); } } } } |
|
public class MusicPlayPresenterImpl implements IMusicPlayPresenter{ //view IMusicPlayView view; //model IMusicPlayModel model; //歌曲列表musics List<Music> musics; //当前播放歌曲在歌曲列表中的下标position int position; boolean isPlaying;//用来记录当前歌曲是处于播放(true)/暂停(false) //构造器 public MusicPlayPresenterImpl(IMusicPlayView view, List<Music> musics, int position) { super(); this.view = view; this.musics = musics; this.position = position; this.model= new MusicPlayModelImpl(); } @Override public void onResume() { String title = musics.get(position).getName(); view.setHeaderViewTitle(title); view.setHeaderViewImage(R.drawable.back, Position.LEFT); view.setHeaderViewImage(R.drawable.statics, Position.RIGHT); view.play(position); isPlaying = true; 进去就播放 } @Override public void onDestroy() { // TODO } @Override public void play() { if(isPlaying){ //暂停音乐的播放 view.pause(position); isPlaying = false; }else{ //播放音乐 view.play(position); isPlaying = true; } }
@Override public void next() { view.pause(position); 先暂停 position += 1; //如果超过了音乐列表中的文件总数 if(position>=musics.size()){ position=0; } view.play(position); view.setHeaderViewTitle(musics.get(position).getName()); //用户可能在两种情况下,按“下一曲” //1)听歌的过程中,直接按“下一曲” //2)先按“暂停”键,再按“下一曲” isPlaying = true; }
@Override public void prev() { view.pause(position); position -= 1; if(position<=0){ position=musics.size()-1; } view.play(position); view.setHeaderViewTitle(musics.get(position).getName()); isPlaying = true; }
@Override public void showDownloadDialog() { view.showDownloadDialog(position); }
@Override public void startDownload(String url) { model.download((Activity)view,url,musics.get(position).getName()); }
@Override public void updateProgress(int current, int duration) { view.updateProgress(current, duration); }
@Override public void seekTo(int progress) { view.seekTo(progress); } }
|
|
public class MusicService extends Service { //音乐播放器 MediaPlayer mediaPlayer; //更新播放进度的线程 Thread updateProgressThread; //按下"暂停"键时,音乐播放到的时间 //当重新开始播放的时候,应该从暂停时位置播放 int seekTime; //音乐播放器是否处在paused状态 //当播放音乐过程中(mediaPlayer处于started状态) //调用mediaPlayer的pause方法,会让mediaPlayer进入paused状态 boolean isPaused; //用来接收PlayActivity发送过来的播放、暂停、快进三种广播 MyReceiver receiver; String pauseUrl;//用来保存按下“暂停”键时,歌曲的URL @Override public void onCreate() { super.onCreate(); //对各种属性进行初始化 //1)mediaPlayer的赋值 mediaPlayer = new MediaPlayer(); //2)mediaPlayer缓冲监听器的添加 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); //mediaPlayer.start(); } }); //3)mediaPlayer当前歌曲播放完毕监听器的添加 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mp.stop(); //向PlayActivity发送广播,播放下一首歌曲 Intent intent = new Intent(Constant.ACTION_UPDATE_MUSIC_PLAYING); sendBroadcast(intent); } }); //4)更新进度线程的创建和启动 updateProgressThread = new Thread(){ public void run() { try { while(!Thread.interrupted()){ 条件:线程没有被打断 if(mediaPlayer.isPlaying()){ //如果mediaPlayer处于播放音乐的状态 //发送广播,更新PlayActivity的sbProgress Intent intent = new Intent(Constant.ACTION_UPDATE_PROGRESS); //歌曲当前播放进度 int currentPosition = mediaPlayer.getCurrentPosition(); //当前播放歌曲的总长度 int duration = mediaPlayer.getDuration(); intent.putExtra("current", currentPosition); intent.putExtra("duration", duration); sendBroadcast(intent); } Thread.sleep(800);隔800毫秒再发广播 } } catch (Exception e) { e.printStackTrace(); } }; }; updateProgressThread.start(); //5)广播接收器的创建和注册 receiver = new MyReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(Constant.ACTION_PLAY_MUSIC); filter.addAction(Constant.ACTION_PAUSE_MUSIC); filter.addAction(Constant.ACTION_SEEKTO_MUSIC); registerReceiver(receiver, filter ); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //修改Service的启动方式为非粘性 return Service.START_NOT_STICKY; } @Override public void onDestroy() { super.onDestroy(); //对各种属性进行"回收" //1)注销广播接收器 unregisterReceiver(receiver); //2)释放mediaPlayer mediaPlayer.release(); //3)结束进度更新线程 //Thread中有这样一个属性boolean flag //调用interrupt方法,会让该属性从false-->true //同时,如果当前Thread对象是处于可中断的阻塞状态时(sleep中) //会抛出一个InterruptException异常 //只要Thread.interrupted()检测到ture或者 //抛出的这个InterruptException异常被捕获 //flag属性就可以从ture回到false updateProgressThread.interrupt(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } /** * MusicServie用来播放指定位置音乐的方法 * @param url */ private void play(String url){ try { if(isPaused && url.equals(pauseUrl)){ //从暂停状态开始继续播放歌曲 mediaPlayer.start();//paused--->started mediaPlayer.seekTo(seekTime);//移动到暂停时的位置 isPaused = false; seekTime = 0; }else{ isPaused = false; seekTime = 0; //全新播放一首歌曲 mediaPlayer.reset(); 重置 mediaPlayer.setDataSource(url); 配置歌曲 mediaPlayer.prepareAsync(); 异步加载 } } catch (Exception e) { e.printStackTrace(); } } /** * MusicService用来暂停音乐播放的方法 */ private void pause(){ isPaused = true; seekTime = mediaPlayer.getCurrentPosition(); mediaPlayer.pause(); } public class MyReceiver extends BroadcastReceiver{
@Override public void onReceive(Context context, Intent intent) { //根据PlayActivity发送过来的不同广播,进行不同的处理 String action = intent.getAction(); if(Constant.ACTION_PLAY_MUSIC.equals(action)){ //收到播放音乐的广播 //要播放的音乐地址从Intent中取出 String url = intent.getStringExtra("url"); play(url); } if(Constant.ACTION_PAUSE_MUSIC.equals(action)){ //收到暂停音乐的广播 pauseUrl = intent.getStringExtra("url"); pause(); } if(Constant.ACTION_SEEKTO_MUSIC.equals(action)){ //收到快进音乐的广播 int progress = intent.getIntExtra("progress",-1); //利用progress换算出要快进到的音乐播放进度 seekTime = (progress*mediaPlayer.getDuration())/100; mediaPlayer.seekTo(seekTime); } } } }
|