android-简单音乐播放器的总结

来源:互联网 发布:集团合并报表软件 编辑:程序博客网 时间:2024/04/19 15:45

业务:android的程序,实现播放音乐的功能。

知识点:

1.使用了android的四大组件中的三个(Activity,Service,Broadcast)

activity与serivice之间的通信用广播Broadcast组件实现,程序中有10多个广播的发布和接收。

2.还使用了线程和Application类来保存全局性的数据。

在Service中启动一个线程是为了在activity需要的时候,不间断地给activity发布更新进度的广播,activity收到后再界面上展示出来。

难点:

个人感觉广播虽然多,但是逻辑上一般,不是很复杂,稍微比较难理解的是线程的启动和停止条件的判段和service中Destroy方法中的收尾清理工作。

1.在这几种条件下需要唤醒线程。

1)play()方法中,当开始播放音乐的时候,让它就开始干活。

2)seekto()方法中,当拖动seekBar需要重新定位并且播放音乐的时候,让它就开始干活。

3)当activity发布广播,请求service发布一个更新进度的广播的时候需要唤醒线程,让它就开始干活。

4)Service方法要退出销毁的时候需要唤醒线程,让其退出循环。

完整项目代码:

http://download.csdn.net/detail/tzguo1314/5542427


部分代码:

主Activity的全部代码

package com.tarena.day1901;import com.tarena.entity.Music;import com.tarena.utils.Consts;import com.tarena.utils.FormatUtils;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuInflater;import android.view.MenuItem;import android.view.View;import android.widget.Button;import android.widget.ListView;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;import android.widget.TextView;public class MainActivity extends Activity {private ListView lvMusics;private MenuInflater inflater;private MusicAdapter adapter;private Button btnPlayOrPause;private MusicApplication app;private TextView tvMusicName;private TextView tvDuration;private InnerBroadcastReceiver receiver;private SeekBar sbProgress;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        inflater=getMenuInflater();         app=(MusicApplication)getApplication();        //设置界面        setupView();        addlistener();        //启动service        Intent intent=new Intent(this, MusicService.class);        startService(intent);        //创建一个广播接收器        createReceiver();    }    //activity启动,发送广播给service告知需要发送进度更新的广播    @Override    protected void onStart() {    super.onStart();        Intent intent=new Intent(Consts.ACTION_NEED_UPDATE_PROGRESS);    intent.putExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, true);    sendBroadcast(intent);    Log.i("info", "onStart");    }    @Override    protected void onResume() {    Log.i("info", "onREsume");    super.onResume();    }  //activity停止,发送广播给service告知可以停止发送进度更新的广播    @Override    protected void onStop() {    super.onStop();    Intent intent=new Intent(Consts.ACTION_NEED_UPDATE_PROGRESS);    intent.putExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, false);    sendBroadcast(intent);    }    @Override    protected void onDestroy() {    super.onDestroy();    unregisterReceiver(receiver);//MainActivity销毁的时候,对广播接收器,解除注册    }     //设置界面    public void setupView(){    lvMusics=(ListView)findViewById(R.id.lvMusics);    adapter=new MusicAdapter(this);    lvMusics.setAdapter(adapter);        btnPlayOrPause=(Button)findViewById(R.id.btnPlayOrPause);    tvMusicName=(TextView)findViewById(R.id.tvMusicName);    tvDuration=(TextView)findViewById(R.id.tvDuration);    sbProgress=(SeekBar)findViewById(R.id.sbProgress);    }    //添加菜单    @Override    public boolean onCreateOptionsMenu(Menu menu) {    inflater.inflate(R.menu.opts,menu);    return super.onCreateOptionsMenu(menu);    }    //选择系统菜单选项,发送广播    @Override    public boolean onOptionsItemSelected(MenuItem item) {    Intent intent=null;    switch (item.getItemId()) {case R.id.menu_sub_loop:intent=new Intent(Consts.ACTION_PLAY_MODE);intent.putExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_LOOP);    sendBroadcast(intent);    Log.i("info", "循环");break;case R.id.menu_sub_random:intent=new Intent(Consts.ACTION_PLAY_MODE);intent.putExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_RADOM);    sendBroadcast(intent);    Log.i("info", "随机");break;case R.id.menu_opts_exit:intent=new Intent(Consts.ACTION_APP_STOPED);    sendBroadcast(intent);finish();break;}    return super.onOptionsItemSelected(item);    }    //监听用户拖动seekbar,并记录拖动的位置    private void addlistener() {  sbProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {if(fromUser){Intent intent=new Intent(Consts.ACTION_SEEK_TO);intent.putExtra(Consts.EXTRA_SEEK_TO, progress);sendBroadcast(intent);}}});    }   //用户不同的操作,执行相应的操作    public void doClick(View v){    Intent intent=null;    switch (v.getId()) {case R.id.btnNext:intent=new Intent(Consts.ACTION_PLAY_NEXT);btnPlayOrPause.setText("暂停");break;case R.id.btnPlayOrPause:String text=((Button)v).getText().toString();if("播放".equals(text)){intent=new Intent(Consts.ACTION_PLAY);((Button)v).setText("暂停");}else if("暂停".equals(text)){intent=new Intent(Consts.ACTION_PAUSE);((Button)v).setText("播放");}break;case R.id.btnPrevious:intent=new Intent(Consts.ACTION_PLAY_PREVIOUS);btnPlayOrPause.setText("暂停");break;}    sendBroadcast(intent);    }    //创建一个广播接收器    private void createReceiver() {     receiver=new InnerBroadcastReceiver();     IntentFilter filter=new IntentFilter();     filter.addAction(Consts.ACTION_CURRENT_MUSIC_CHANGE);     filter.addAction(Consts.ACTION_START_UPDATE_PROGRESS);     filter.addAction(Consts.ACTION_SEND_PLAYING_STATE);     registerReceiver(receiver, filter);}        private class InnerBroadcastReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {String action=intent.getAction();//接收广播,音乐变更,前端展示更新为新的音乐的名字和时长if(Consts.ACTION_CURRENT_MUSIC_CHANGE.equals(action)){Music music=app.getCurrentMusic();tvMusicName.setText(music.getName());tvDuration.setText(FormatUtils.format(music.getDuration()));}else if(Consts.ACTION_START_UPDATE_PROGRESS.equals(action)){//当前播放时长int progress=intent.getIntExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, 0);//总时长int Duration = (int)app.getCurrentMusic().getDuration();tvDuration.setText(FormatUtils.format(progress));//在界面显示歌曲已播放时长sbProgress.setProgress(progress*100/Duration);}else if(Consts.ACTION_SEND_PLAYING_STATE.equals(action)){int state=intent.getIntExtra(Consts.EXTRA_PLAY_STATE, Consts.STATE_OTHERS);Music m=app.getCurrentMusic();int progress=intent.getIntExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, 0);int Duration = (int)app.getCurrentMusic().getDuration();tvDuration.setText(FormatUtils.format(progress));//在界面显示歌曲已播放时长sbProgress.setProgress(progress*100/Duration);tvMusicName.setText(m.getName());if(state==Consts.STATE_PAUSE){btnPlayOrPause.setText("播放");}else if(state==Consts.STATE_ISPLAYING){btnPlayOrPause.setText("暂停");}}}    }  }


MusicService的完整代码


package com.tarena.day1901;import java.io.IOException;import java.util.Random;import com.tarena.entity.Music;import com.tarena.utils.Consts;import android.app.Service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.os.IBinder;import android.util.Log;public class MusicService extends Service {private MediaPlayer player;private MusicApplication app;private boolean isPause;private boolean needUpdate; //需要发布更新进度private boolean isLoop;//控制循环语句private int playMode;private Random random;private InnerBroadcastReceiver receiver;private Thread workThread;@Overridepublic void onCreate() {super.onCreate();app=(MusicApplication)getApplication();player=new MediaPlayer();playMode=Consts.PLAY_MODE_LOOP;isLoop=true;needUpdate=true;random=new Random();//设置自动播放下一首的监听器addlistener();//添加接收器createReceiver();workThread=new Thread(){public void run() {while(isLoop){while(isLoop&&needUpdate&&player.isPlaying()){Intent intent=new Intent(Consts.ACTION_START_UPDATE_PROGRESS);//将当前播放的音乐播放的时间抽的位置包装传递intent.putExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, player.getCurrentPosition());sendBroadcast(intent);try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}//此工作线程需要不停地循环工作,除非修改循环标志。不需要发送广播的时候就等待,睡大觉synchronized (this) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}}};};workThread.start();}//service销毁的时候,解除注册广播接收器@Overridepublic void onDestroy() {unregisterReceiver(receiver);//唤醒线程,让线程退出循环isLoop = false;synchronized (workThread) {workThread.notify();}//如果音乐还在播放,停止其播放if (player.isPlaying())player.stop();//释放资源player.release();super.onDestroy();}//如果是isPause状态值为true,直接播放,else重置player,最后要记得唤醒线程public void play(){if(isPause){player.start();}else{Music music=app.getCurrentMusic();String path=music.getMusicPath();if(path!=null){try {player.reset();player.setDataSource(path);player.prepare();player.start();//当前索引所表示的歌曲变化,发布广播Intent intent=new Intent(Consts.ACTION_CURRENT_MUSIC_CHANGE);sendBroadcast(intent);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}isPause=false;//音乐开始播放,将暂停状态标志置为falsesynchronized (workThread) {workThread.notify();}}//如果正在播放,暂停播放public void pause(){if(player.isPlaying()){player.pause();isPause=true;}}//开始播放后一首public void next(){int index=app.getCurrentPosition();switch (playMode) {case Consts.PLAY_MODE_LOOP:if(++index>=app.getPlayListSize()){index=0;}break;case Consts.PLAY_MODE_RADOM:do {index=random.nextInt(app.getPlayListSize());} while (index==app.getCurrentPosition());break;}app.setCurrentPosition(index);isPause=false;play();}//开始播放前一首public void previous(){int index=app.getCurrentPosition();switch (playMode) {case Consts.PLAY_MODE_LOOP:if(--index<=0){index=app.getPlayListSize()-1;}break;case Consts.PLAY_MODE_RADOM:do {index=random.nextInt(app.getPlayListSize());} while (index==app.getCurrentPosition());break;}app.setCurrentPosition(index);isPause=false;play();}//定位到指定的时间值开始播放public void seekTo(int positon){player.seekTo(positon);player.start();synchronized (workThread) {workThread.notify();}}@Overridepublic IBinder onBind(Intent intent) {return null;}//设置自动播放下一首public void addlistener(){player.setOnCompletionListener(new OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {next();}});}//添加接收器private void createReceiver() {receiver=new InnerBroadcastReceiver();IntentFilter filter=new IntentFilter();filter.addAction(Consts.ACTION_PAUSE);filter.addAction(Consts.ACTION_PLAY);filter.addAction(Consts.ACTION_PLAY_NEXT);filter.addAction(Consts.ACTION_PLAY_PREVIOUS);filter.addAction(Consts.ACTION_PLAY_MODE);filter.addAction(Consts.ACTION_APP_STOPED);filter.addAction(Consts.ACTION_NEED_UPDATE_PROGRESS);filter.addAction(Consts.ACTION_SEEK_TO);registerReceiver(receiver, filter);}//接收器类private class InnerBroadcastReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {String action=intent.getAction();if(Consts.ACTION_PLAY.equals(action)){play();}else if(Consts.ACTION_PAUSE.equals(action)){pause();}else if(Consts.ACTION_PLAY_NEXT.equals(action)){next();}else if(Consts.ACTION_PLAY_PREVIOUS.equals(action)){previous();}else if(Consts.ACTION_PLAY_MODE.equals(action)){playMode=intent.getIntExtra(Consts.EXTRA_PLAY_MODE, Consts.PLAY_MODE_LOOP);}//获取并判断当前是否需要发送更新进度的广播else if(Consts.ACTION_NEED_UPDATE_PROGRESS.equals(action)){needUpdate=intent.getBooleanExtra(Consts.EXTRA_NEED_UPDATE_PROGRESS, true);if(needUpdate){synchronized (workThread) {workThread.notify();}//更新进度的时候,同时发送音乐播放器的状态(是否正在播放、播放的音乐的位置)Intent intent2=new Intent(Consts.ACTION_SEND_PLAYING_STATE);int state=Consts.STATE_OTHERS;int position=0;if(player.isPlaying()){state=Consts.STATE_ISPLAYING;}else if(isPause){state=Consts.STATE_PAUSE;}position=player.getCurrentPosition();intent2.putExtra(Consts.EXTRA_CURRENT_MUSIC_TIME_POSITION, position);intent2.putExtra(Consts.EXTRA_PLAY_STATE, state);sendBroadcast(intent2);}//根据拖动的位置,计算应当开始播放的时间值}else if(Consts.ACTION_SEEK_TO.equals(action)){int progress=intent.getIntExtra(Consts.EXTRA_SEEK_TO, player.getCurrentPosition());int duration=(int)app.getCurrentMusic().getDuration();seekTo(progress*duration/100);}else if(Consts.ACTION_APP_STOPED.equals(action)){stopSelf();}}}}


原创粉丝点击