120分钟孕育一个小小的MP3播放器

来源:互联网 发布:.node文件类型 编辑:程序博客网 时间:2024/04/29 12:18
花了2个多小时,完成了一个小小的Android MP3播放器,在各位大牛看来是小菜一碟
对于新手的我来说,还是有一定成就感的,好吧,斗胆拿出来分享一下,希望大神们多提意见。
1.简单说下我的构思,我想做两个页面,登录程序后,首先展示的是SD卡下的所有MP3文件,
点击某一首歌曲后,跳转到第二个页面进行控制播放,暂停等功能,只有完全退出程序才关闭停止歌曲....
2.第一步,对项目进行分下包,虽然项目很小,但是我觉得无论多小的项目,分包应该都是要
认真对待的。我这里主要分为4个包.....
第一个包下面有两个文件:MainActivity是主界面,PlayActivity是播放界面
control包下面是一个列表适配器的定义文件
model包下面是歌曲的Bean文件
utils包下面是一些封装好的方法
3.我的布局文件有3个
看下主界面的布局先,就是activity_main.xml文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <ListView         android:id="@+id/showSongList"        android:layout_width="match_parent"        android:layout_height="match_parent"        >    </ListView></RelativeLayout>


很简单,就是一个ListView....
再看下播放界面的布局文件,就是playsong.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView         android:id="@+id/tView"        android:layout_marginTop="30dp"                android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="\n\n\n正在播放\n1.XXXXX"                />    <ImageView         android:id="@+id/igView"        android:layout_gravity="center"        android:layout_marginTop="30dp"                android:layout_width="200dp"        android:layout_height="400dp"        />            <SeekBar         android:id="@+id/skBar"        android:layout_gravity="center_vertical|center"        android:layout_height="wrap_content"        android:layout_width="200dp"                />        <LinearLayout             android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_vertical|center"            android:layout_marginTop="30dp"            android:orientation="horizontal">            <Button                 android:id="@+id/preBtn"                android:layout_width="80dp"                android:layout_height="wrap_content"                android:gravity="center_horizontal"                android:text="@string/preSong"                />            <Button                 android:id="@+id/playBtn"                android:layout_width="80dp"                android:layout_height="wrap_content"                android:gravity="center_horizontal"                android:text="@string/startPlay"                />            <Button                 android:id="@+id/pauseBtn"                android:layout_width="80dp"                android:layout_height="wrap_content"                android:gravity="center_horizontal"                android:text="@string/pausePlay"                />            <Button                 android:id="@+id/nextBtn"                android:layout_width="80dp"                android:layout_height="wrap_content"                android:gravity="center_horizontal"                android:text="@string/nextSong"                />        </LinearLayout></LinearLayout>


也很简单...贴上一副图片,你就能明白了....
第三个布局文件是list_song_item.xml,它用来定义ListView中每一项的内容...
就是适配器用的布局文件...这里我只写了一个TextView...
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal" >    <TextView         android:id="@+id/songInfo"        android:layout_width="match_parent"        android:layout_height="60dp"      android:gravity="left|center_vertical"       android:textSize="30sp"        /></LinearLayout>


4.看下MainActivity的代码吧..
public class MainActivity extends Activity {    private ListView lv ;        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //找到ListView        lv = (ListView)findViewById(R.id.showSongList);        //设置适配器        lv.setAdapter(new SongAdapter(this));        //点击某一项后跳转到播放页面        lv.setOnItemClickListener(new OnItemClickListener() {            public void onItemClick(AdapterView<?> arg0, View arg1, int position,                    long arg3) {                // TODO Auto-generated method stub                Intent intent = new Intent(MainActivity.this, PlayActivity.class);                //携带要播放歌曲的序号                intent.putExtra("pos",position);                //开始跳转                startActivity(intent);            }        });    }        /* (non-Javadoc)     * @see android.app.Activity#onKeyUp(int, android.view.KeyEvent)     */    @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {        // TODO Auto-generated method stub        if(keyCode == KeyEvent.KEYCODE_BACK)        {            //按返回键的时候,设置哨兵isExit,终止播放歌曲..            PlayActivity.isExit = true;                    }        return super.onKeyUp(keyCode, event);    }

比如我点击第一首,就会跳转到播放页面
5.看下播放页面的代码PlayActivity.Java...有一点很关键,就是
那个MediaPlayer,因为用户每点一次歌曲都会跳转到这个页面,
不可能同时有几个MediaPlayer工作,所以整个程序只维护一个
MediaPlayer...
public class PlayActivity extends Activity implements OnClickListener{        //当isExit = ture的时候,终止线程    public static boolean isExit;    //有且只有一个MediaPlayer    private  static MediaPlayer mp = new MediaPlayer();    //所用到的控件    private TextView tView;    private ImageView igView;    private Button nextBtn;    private Button preBtn;    private Button playBtn;    private Button pauseBtn;    private SeekBar skBar;    private int curPlayIndex;    private SongControl sc;    //获取所有歌曲列表    private ArrayList<SongBean> songList;    //当点击上一首,或下一首的时候设置该变量    private boolean indexChange;    //线程    private  Thread songThread;    /* (non-Javadoc)     * @see android.app.Activity#onCreate(android.os.Bundle)     */    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        setContentView(R.layout.playsong);        sc = SongControl.newInstance();        songList = sc.getSongList();        indexChange = true;        isExit = false;                        tView = (TextView)findViewById(R.id.tView);        igView = (ImageView)findViewById(R.id.igView);        nextBtn = (Button) findViewById(R.id.nextBtn);        preBtn = (Button)findViewById(R.id.preBtn);        playBtn = (Button)findViewById(R.id.playBtn);        pauseBtn = (Button)findViewById(R.id.pauseBtn);        skBar = (SeekBar)findViewById(R.id.skBar);        //设置SeekBar侦听        skBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {                        public void onStopTrackingTouch(SeekBar seekBar) {                // TODO Auto-generated method stub                //拖到最后的时候,直接播放下一首歌曲                if(seekBar.getProgress() == mp.getDuration())                {                    nextSong();                }                mp.seekTo(seekBar.getProgress());            }                        public void onStartTrackingTouch(SeekBar seekBar) {                // TODO Auto-generated method stub                            }                        public void onProgressChanged(SeekBar seekBar, int progress,                    boolean fromUser) {                // TODO Auto-generated method stub                            }        });        songThread = new Thread(new Runnable() {                        public void run() {                // TODO Auto-generated method stub                while(true)                {                    //如果是true,终止线程                    if(isExit)                    {                        stopSong();                        break;                    }                    if(mp.isPlaying())                    {                        try {                            Thread.sleep(500);                            skBar.setProgress(mp.getCurrentPosition());                        } catch (InterruptedException e) {                            // TODO Auto-generated catch block                            e.printStackTrace();                        }                    }                }            }        });        songThread.start();                        nextBtn.setOnClickListener(this);        preBtn.setOnClickListener(this);        playBtn.setOnClickListener(this);        pauseBtn.setOnClickListener(this);        //        curPlayIndex = getIntent().getIntExtra("pos", 0);                playSong();    }    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.preBtn:            preSong();            break;        case R.id.nextBtn:            nextSong();            break;        case R.id.playBtn:            playSong();            break;        case R.id.pauseBtn:            pauseSong();            break;                    default:            break;        }    }        //播放歌曲触发的动作    public void playSong()    {        try {            if (indexChange) {                mp.reset();                mp.setDataSource(songList.get(curPlayIndex).getSongPath());                mp.prepare();                skBar.setMax(mp.getDuration());                //设置title                setTitle();                //设置图片背景                igView.setBackgroundResource(songList.get(curPlayIndex).getSongPhoto());            }            mp.start();            indexChange = false;        } catch (IllegalArgumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (SecurityException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalStateException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }        public void pauseSong()    {        if(mp.isPlaying())        {            mp.pause();        }    }    public void nextSong()    {        if(curPlayIndex!=songList.size()-1)        {            curPlayIndex++;            indexChange=true;            playSong();        }    }    public void preSong()    {        if(curPlayIndex!=0)        {            curPlayIndex--;            indexChange=true;            playSong();        }    }        public  void stopSong()    {        mp.stop();        mp.release();    }        /* (non-Javadoc)     * @see android.app.Activity#onKeyUp(int, android.view.KeyEvent)     */    @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {        // TODO Auto-generated method stub        if(keyCode == KeyEvent.KEYCODE_BACK)        {            this.finish();            return true;        }        return super.onKeyUp(keyCode, event);    }        public void setTitle()    {        String nextSongName = curPlayIndex == songList.size()-1?"无":songList.get(curPlayIndex+1).getSongName();        tView.setText("正在播放:"+songList.get(curPlayIndex).getSongName()+"\n接着要播放:"+nextSongName);    }}

6.SongBean文件,截个图吧
7.SongControl文件...封装一些方法
public class SongControl {        private ArrayList<SongBean> songList;    private MediaPlayer mp;    private final int[] Images = new int[] {R.drawable.b1,R.drawable.b2};        public static SongControl newInstance()    {        SongControl sc = new SongControl();        sc.songList = new ArrayList<SongBean>();        sc.mp = new MediaPlayer();        return sc;    }    //获取SD卡的路径    public String getRootPath()    {        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))        {            return Environment.getExternalStorageDirectory().getPath();        }        else        {            return "/";        }    }    //获取所有歌曲列表    public ArrayList<SongBean> getSongList()    {        return loadData(getRootPath(),new FileFilter() {                        public boolean accept(File pathname) {                // TODO Auto-generated method stub                return pathname.getPath().endsWith("mp3");             }        });    }    //加载数据    public ArrayList<SongBean> loadData(String path,FileFilter myFilter)    {        int index = 0;        File fileSet = new File(path);        if(fileSet.exists()&&fileSet.isDirectory())        {            for(File file : fileSet.listFiles(myFilter))            {                SongBean sb = new SongBean();                sb.setSongName(file.getName());                sb.setSinger("hjq");                sb.setSongDuration(getSongTime(file.getPath()));                sb.setSongPath(file.getPath());                sb.setSongPhoto(Images[index]);                songList.add(sb);                index++;            }            return songList;        }        else        {            return null;        }    }    //获取歌曲的时间    public String getSongTime(String path)    {        mp.reset();        try {            mp.setDataSource(path);            mp.prepare();            int times =  mp.getDuration()/1000;            int hour = 0;            int min = 0;            int sec = 0 ;            if(times>3600)            {                hour = times/3600;                times%=3600;            }            if(times>60)            {                min = times/60;                times%=60;                sec = times;            }            return 0==hour?hour+":"+min+":"+sec:min+":"+sec;                    } catch (IllegalArgumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (SecurityException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalStateException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return null;    }

那个适配器的话,很简单,就不贴上了....
哎,不容易啊,看来还有很长的路要走....



原创粉丝点击