zoukankan      html  css  js  c++  java
  • Android 凑热闹的MusicPlay

    前言

      这阵子都在做android相关的开发。写了一个基于MediaPlayer类的MusicPlay——音乐播放 器。因为Demo很简单所 以把什么代码都写在了Activity下,相当严重的坏代码味道(-_-||)。程序实现了歌曲的播放、暂停、停止、上下首、进度条控制、歌曲列表这些功 能,Demo是基于android 2.2版本的。这里把一些关键代码列举出,分析一下。

    歌曲列表

      我很穷 没有android手机(公司也不给我们配一台~~),全都是用模拟器进行调试的。开发前需要新建一个带SD卡的模拟器,然后把歌曲 添加到模拟器中。在添加歌曲时遇到一个问题,不管我是用命令行添加,还是使用File Explorer,把歌曲PUSH到模拟器的SD卡里。当我再次读出歌曲名称时都遇到了中文乱码,研究发现存储在模拟器上歌曲名称本身就已经是乱码了,问 题出现在PUSH方式上。后来在网上找到了一个解决方法,因为模拟器的SD卡是 img格式的镜像文件,于是我用UltraISO打开,把歌曲放进去再保存成Img文件,中文名乱码问题就解决了。
      用一个ListView来显示歌曲列表,使用 ArrayAdapter<String> adapter 简单的将歌曲绑定到ListView上。从SD卡上获取文件我们需要新建一个文件过滤器类,这个类需要实现FilenameFilter接口。
     
    复制代码
    1 //文件过滤器
    2  class MusicFilter implements FilenameFilter {
    3
    4 @Override
    5 publicboolean accept(File dir, String filename) {
    6
    7 return (filename.endsWith(".mp3"));
    8 }
    9
    10 }
    复制代码
      获取歌曲列表
    复制代码
    1 /**
    2 * 播放列表
    3 */
    4 publicvoid MusicList() {
    5 try {
    6 File home =new File(PATH);
    7
    8 File[] f = home.listFiles(new MusicFilter());
    9 if (f.length >0) {
    10 for (int i =0; i < f.length; i++)
    11 {
    12
    13 File file = f[i];
    14 byte[] bytes=file.getName().getBytes("GB2312");
    15 String name=new String(bytes,"GB2312");
    16 musicList.add(name);
    17 }
    18 ArrayAdapter<String> adapter =new ArrayAdapter<String>(this,
    19 android.R.layout.simple_list_item_single_choice, musicList);
    20 songList.setAdapter(adapter);
    21 }
    22 }
    23 catch (Exception ex)
    24 {
    25 Toast.makeText(this, "显示音乐列表异常:"+ ex.getMessage(), Toast.LENGTH_LONG).show();
    26 }
    27
    28 }
    复制代码

      还需要为歌曲列表添加点击是的响应处理,点击某些Item时将播放该歌曲

    @Override
    publicvoid onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    // TODO Auto-generated method stub
    currentSong=arg2;
    playMusic(PATH
    +musicList.get(currentSong));
    }

    歌曲播放

      使用MediaPlayer对歌曲播放进行控制。需要注意的是对播放状态的控制。
    复制代码
    publicvoid playMusic(String path) {
    try
    {
    if(isPlaying)
    {
    player.stop();
    }
    player.reset();
    player.setDataSource(path);
    player.prepare();
    player.start();
    isPlaying
    =true;
    isPause
    =false;
    isStop
    =false;
    //设置进度条
    barCount = player.getDuration();
    bar.setMax(barCount);
    // 设置最大值.
    String time=formatTime(barCount);

    txtTotalTime.setText(time);
    txtPlaying.setText("当前播放歌曲:"+this.musicList.get(this.currentSong));
    btnPlay .setImageResource(R.drawable.pause);
    songList.setItemChecked(currentSong, true);
    }
    catch (IOException e)
    {
    // TODO Auto-generated catch block
    Log.v(getString(R.string.app_name), e.getMessage());
    }
    }
    复制代码

    暂停、停止、完成播放

      这几个操作比较简单,主要是调用MediaPlayer的对应方法,然注意修改View的状态(这里应该将View状态修改提取出来的,有写职责混乱)
    复制代码
    protectedvoid pause() {
    if (player.isPlaying()) {
    player.stop();
    // 停止
    this.btnPlay .setImageResource(R.drawable.play);
    this.txtPlaying.setText("暂停播放歌曲:"+this.musicList.get(this.currentSong));
    this.isPause=true;
    this.isPlaying=false;
    this.isStop=false;
    }
    }
    复制代码
    复制代码
    publicvoid stopMusic() {
    this.isPlaying =false;
    this.isStop=true;
    this.isPause=false;
    this.btnPlay .setImageResource(R.drawable.play);
    this.txtPlaying.setText("停止播放");
    if (player.isPlaying())
    {
    player.stop();
    // 停止
    }
    }
    复制代码
      需要监听播放完一首歌曲后应当播放下一首,这里需要监听播放完成事件  player.setOnCompletionListener(this); 
    复制代码
    @Override
    publicvoid onCompletion(MediaPlayer arg0) {
    // TODO Auto-generated method stub
    try
    {
    nextMusic();
    }
    catch (Exception e)
    {
    txtPlaying.setText(e.toString());
    e.printStackTrace();
    }
    }
    复制代码

    上一首、下一首播放

      代码比较简单就直接贴出来了
    复制代码
    publicvoid nextMusic() {
    int num =this.musicList.size();
    if (++this.currentSong >= num) {
    currentSong
    =0;
    }
    stopMusic();
    playMusic(PATH
    + musicList.get(currentSong));

    }
    复制代码
    复制代码
    publicvoid lastMusic() {
    int num = musicList.size();
    if (--currentSong <0) {
    currentSong
    = num -1;
    }
    stopMusic();
    playMusic(PATH
    + musicList.get(currentSong));

    }
    复制代码
      这些就是对播放的基本控制了。除了这个以外我们还需要对播放错误进行监听     player.setOnErrorListener(this);
    复制代码
    @Override
    publicboolean onError(MediaPlayer mp, int what, int extra) {
    // TODO Auto-generated method stub
    try
    {
    /*发生错误时也解除资源与MediaPlayer的赋值*/
    mp.release();
    mp.reset();
    this.txtPlaying.setText("播放发生异常!");
    }
    catch (Exception e)
    {
    this.txtPlaying.setText(e.toString());
    e.printStackTrace();
    }

    returnfalse;
    }
    复制代码

    进度条

      进度条用来显示当前歌曲的播放进度,同时还需要具有拖拽定点播放功能。这里需要使用到线程和消息机制。Demo中我让Activity实现了Runnable接口。
    复制代码
    @Override
    publicvoid run() {
    // TODO Auto-generated method stub
    while (true) {
    try {

    int n = player.getCurrentPosition();
    Message msg
    =new Message();
    msg.what
    = n;
    handler.sendMessage(msg);

    Thread.sleep(
    100);
    }
    catch (Exception ex) {
    ex.printStackTrace();
    }

    }

    }
    复制代码
      消息处理代码
    复制代码
    public Handler handler =new Handler() {
    publicvoid handleMessage(Message msg) {
    super.handleMessage(msg);
    bar.setProgress(msg.what);
    currentBar
    =msg.what;
    if(isPlaying)
    {
    String time
    =formatTime(msg.what);
    txtNowTime.setText(time);
    }
    bar.invalidate();
    }
    };
    复制代码

      拖动进度条是的定点播放

    复制代码
    bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

    @Override
    publicvoid onStopTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
    bar.setProgress(currentBar);
    player.seekTo(currentBar);
    }

    @Override
    publicvoid onStartTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub

    }

    @Override
    publicvoid onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
    // TODO Auto-generated method stub
    currentBar=progress;
    }
    });
    复制代码

    小结

      MusicPlay的各项功能主要是通过对MediaPlayer类的调用实现的。程序中具有较重的“代码坏味道”,等有空需要整理整理。
    【转载】http://www.cnblogs.com/keyindex/archive/2010/08/20/Musicplay-android.html
  • 相关阅读:
    ADO.NET 3.5高级编程:应用LINQ&Entity Framework
    C#高级编程(第8版)
    ASP.NET MVC 4 Web编程
    Version of SQLCE in WP8
    字符圆角尖角实现对话框
    数字跳动放大
    jquery框架和mvvm框架的类名操作性对比
    按钮也是一门大学问
    图片轮播
    滑动显示大图升级版
  • 原文地址:https://www.cnblogs.com/jidan/p/3432855.html
Copyright © 2011-2022 走看看