Android开发实战之简单音乐播放器

最近开始学习音频相关。所以,很想自己做一个音乐播放器,于是,花了一天学习,将播放器的基本功能实现了出来。我觉得学习知识点还是蛮多的,所以写篇博客总结一下关于一个音乐播放器实现的逻辑。希望这篇博文对你的学习和生活有所帮助。效果图:

**实现逻辑**

在市面上的音乐播放app,即时你关了。那么一样会在后台播放,所以播放的逻辑应该写在Service中。并且能够实现Service和Activity之间进行通信。那么Service是四大组件之一,所以在使用的时候一定不要忘了在配置文件中声明一下。

     <service android:name="com.yakir.services.MusicService">

        </service>

我们需要重写Service中的三个方法,onCreate(),onStartCommand(),onDestroy()。

onCreate():Service第一次启动的时候调用这个方法,可以做一些变量的初始化。

onStartCommand():Service每一次启动的时候调用这个方法,可以在此方法写一些业务逻辑。

onDestroy():Service销毁的时候调用,用于释放资源。

接下来,如果需要播放一个音乐文件,可以使用安卓自带的播放器MediaPlayer,将播放逻辑封装起来:

    //开始
    public void start(String path) {
        try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(path);
            mediaPlayer.prepare();
            mediaPlayer.start();
            MediaUtils.currentState= Constants.PLAY_START;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //暂停
    public void pause (){
        if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
            MediaUtils.currentState=Constants.PLAY_PAUSE;
        }
    }
    //继续播放
    public void continuePlay() {
        if (mediaPlayer!=null&&!mediaPlayer.isPlaying()) {
            mediaPlayer.start();
            MediaUtils.currentState= Constants.PLAY_START;
        }
    }
    //停止播放
    public void stop() {
        if (mediaPlayer!=null) {
            mediaPlayer.stop();
            MediaUtils.currentState=Constants.PLAY_STOP;
        }
    }

我们知道,UI是写在Activity中的,那么就涉及到Activity与Service之间进行通信,他们之间通信的方式有5种,这里我是用了Intent,调用startService()进行通信,

同时让Intent携带一组键值对数据,与Service端进行匹配。

Activity:

   private void startMusicService(String option,String path) {
        Intent intentService = new Intent(MainActivity.this, MusicService.class);
        intentService.putExtra("option", option);
        intentService.putExtra("messenger",new Messenger(handler));
        intentService.putExtra("path", path);
        startService(intentService);
    }
    private void startMusicService(String option) {
        Intent intentService = new Intent(MainActivity.this, MusicService.class);
        intentService.putExtra("option", option);
        intentService.putExtra("messenger",new Messenger(handler));
        startService(intentService);
    }
    private void startMusicService(String option,int progress) {
        Intent intentService = new Intent(MainActivity.this, MusicService.class);
        intentService.putExtra("option", option);
        intentService.putExtra("progress",progress);
        intentService.putExtra("messenger",new Messenger(handler));
        startService(intentService);
    }

Service:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("thread",Thread.currentThread().getName() );
        String option=intent.getStringExtra("option");
        if (messenger==null) {
            messenger = (Messenger) intent.getExtras().get("messenger");
        }
        if ("开始".equals(option)) {
            start(intent.getStringExtra("path"));
        } else if ("暂停".equals(option)) {
            pause();
        } else if ("继续".equals(option)) {
            continuePlay();
        } else if ("停止".equals(option)) {
            stop();
        } else if ("跳转".equals(option)) {
            seekPlay(intent.getIntExtra("progress",-1));
        }
        return super.onStartCommand(intent, flags, startId);
    }

这样,就实现了两者之间的通信,接下来,当我点击下一首的时候,那么下一个item的文字高亮,并且播放下一首歌。

先从系统中拿到所有的音频数据:

   public static void getSongList (Context context) {
        musicBeanList.clear();
        Uri uri= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        Cursor cursor=context.getContentResolver().query(uri,
                new String[]{
                        MediaStore.Audio.Media.TITLE,
                        MediaStore.Audio.Media.ARTIST,
                        MediaStore.Audio.Media.DATA},null,null,null);
        while (cursor.moveToNext()) {
            musicBeanList.add(new MusicBean(
                    cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)),
                    cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)),
                    cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))));
        }
    }

通过内容提供者,拿到系统的所有音频数据,以及音频的相关信息。DATA就是音频路径,拿到音频路径后就可以根据现实位置进行播放切换了。(这里很简单,不细说)

处理文字高亮:

我们需要知道当前的item位置和下一个item位置,当点击下一首歌曲,下个位置高亮,其他位置不亮。所以,需要我们定义一个常量记录当前位置,并且,当点击下一首,常量增加,上一首,常量减少。

   case R.id.ib_bottom_last:
                  setColor(Color.BLUE);
                  MediaUtils.currentPosition--;
                  setColor(Color.RED);
                  startMusicService("开始",MediaUtils.musicBeanList.get(MediaUtils.currentPosition).path);
                  imgBottomPlay.setImageResource(R.drawable.appwidget_pause);
              break;
          case R.id.ib_bottom_next:
                  setColor(Color.BLUE);
                  MediaUtils.currentPosition++;
                  setColor(Color.RED);
                  startMusicService("开始",MediaUtils.musicBeanList.get(MediaUtils.currentPosition).path);
                  imgBottomPlay.setImageResource(R.drawable.appwidget_pause);
              break;

需要在改变颜色时做一下逻辑处理:

当到最后一个item时点击下一个高亮变为第一个,当位于第一个时,点击上一首,高亮位于最后一个位置。

  private void setColor(int color) {
        if (MediaUtils.currentPosition==MediaUtils.musicBeanList.size()) {
            MediaUtils.currentPosition=0;
        }
        if (MediaUtils.currentPosition==-1) {
            MediaUtils.currentPosition=MediaUtils.musicBeanList.size()-1;
        }
        TextView textView= (TextView) songList.findViewWithTag(MediaUtils.currentPosition);
        if (textView!=null) {
            textView.setTextColor(color);
        }

    }

接下来,需要实现一个更随音乐播放进度的进度条,这就需要实现Service向Activity的通信,可以通过消息机制,让Service发送消息给Activity,将播放信息传递给Activity.

拿着这个Intent传一个信使(Messager).

intentService.putExtra("messenger",new Messenger(handler));

从而Service:

                                Message message=Message.obtain();
                                message.arg1=currentPostion;
                                message.arg2=duration;
                                message.what=Constants.MUSIC_PREPARE;
                                messenger.send(message);

Activity再处理:

    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Constants.MUSIC_PREPARE:
                    int curduration=msg.arg1;
                    int totalduration=msg.arg2;
                    tv_curduration.setText(MediaUtils.duration2Str(curduration));
                    tv_totalduration.setText(MediaUtils.duration2Str(totalduration));
                    sk_duration.setMax(totalduration);
                    sk_duration.setProgress(curduration);
                    break;
            }
        }
    };

在SeekBar中设置监听,当拖动停止时把当前进度传给Service,让音乐就当前位置播放:

   sk_duration.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                 sk_duration.setProgress(seekBar.getProgress());
                startMusicService("跳转",seekBar.getProgress());
            }
        });

同时,我们需要注意到一个情况,当启动电话时,音乐应该是停止状态,可以通过AudioManager获得音频焦点,当焦点失去时,音乐也应该停止:

     AudioManager audioManager= (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.requestAudioFocus(new AudioManager.OnAudioFocusChangeListener() {
            @Override
            public void onAudioFocusChange(int focusChange) {
                switch (focusChange) {
                    case AudioManager.AUDIOFOCUS_GAIN:
                        mediaPlayer.start();
                        mediaPlayer.setVolume(1.f,2.0f);
                        break;
                    case AudioManager.AUDIOFOCUS_LOSS:
                        if (mediaPlayer.isPlaying())
                            mediaPlayer.stop();
                            mediaPlayer.release();
                            mediaPlayer=null;
                        break;
                    case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
                        if (mediaPlayer.isPlaying());
                        mediaPlayer.pause();
                        break;
                }

            }
        },AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN);

好了,这样一个简单的音乐播放器就完成了,虽然说代码不是很困难,但是还是有很多知识点,比如Activity中Service中的通信,以及ListView相关,还有程序的逻辑性,所以我把几个重要的点总结了一下。希望这篇博文对你的生活和学习有所帮助,如果有什么疑问可以在下方留言,如果你想要源码,可以私聊我~

时间: 2024-10-11 05:48:41

Android开发实战之简单音乐播放器的相关文章

安卓开发,实现简单音乐播放器

Android平台多媒体框架核心使用的是OpenCORE多媒体框架,在安卓系统中所有涉及音频视频的录制.解码.播放都是通过它来实现的.Android系统音频视频以及流媒体类型数据的播放有MediaPlayer类来完成. 下面进行一个实例来演示MediaPlayer的使用: 具体实现效果如下: 其中选项1,2,3分别是三种不同的音频加载方式: 方式1是内部加载,音频文件存放在/res/raw文件夹中, 方式2是本地加载,音频文件存放在本地SD卡中, 方式三为网络加载,音频文件从网络中获取. xml

Android开发---MediaPlayer简单音乐播放器

Android开发-MediaPlayer简单音乐播放器 功能介绍 实现一个简单的播放器,类似网易云音乐形式,功能包括: 播放.暂停,停止,退出功能: 后台播放功能: 进度条显示播放进度.拖动进度条改变进度功能: 播放时图片旋转,显示当前播放时间功能: 界面样式 功能实现 1. MediaPlayer的实现 MediaPlayer常用方法介绍 MediaPlayer的实现包括初始化MediaPlayer,MediaPlayer的功能实现,包括播放.暂停.停止.离开等,具体细节如下: MediaP

HTML5之audio实战,网页音乐播放器开发

今天我们就基于 HTML5 audio  来,开发一个网页音乐播放器. 在HTML5 新特性中,audio .video 是我们比较关心的 新 元素,我们终于可以脱离 Flash ,来开发音频.视频播放器了,对于 一个HTML 新元素,无非就是 属性.事件 .方法等等,关于audio 的具体的属性.事件 .方法,请谷歌. 看我们的HTML代码: audio.html <!DOCTYPE html> <html> <head> <meta charset="

Android 实现简单音乐播放器(一)

今天掐指一算,学习Android长达近两个月了,今天开始,对过去一段时间的学习收获以及遇到的疑难杂症做一些总结. 简单音乐播放器是我自己完成的第一个功能较为完整的APP,可以说是我的Android学习之路上的一个小小里程碑,给我增加了很多信心(~~真容易获得满足~~).从下面开始,我将详细介绍MusicPlayer的设计过程. 首先,先看一下这个项目的工程目录和运行效果:      从上面的图片看到,整个工程的布局文件有两个:activity_main.xml和musiclist.xml,其中,

Android——简单音乐播放器

使用MediaPlayer做的简单音乐播放器,更多内容请到百度经验查看   http://jingyan.baidu.com/article/60ccbceb63452364cab197f1.html <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:l

Android 实现简单音乐播放器(二)

在Android 实现简单音乐播放器(一)中,我介绍了MusicPlayer的页面设计. 现在,我将解析MusicPlayer的功能实现,就讲一些主要的点和有趣的细节,结合MainActivity.java代码进行说明(写出来可能有点碎……一向不太会总结^·^). 一.功能菜单 在MusicPlayer中,我添加了三个菜单: search(搜索手机中的音乐文件,更新播放列表). clear(清除播放列表……这个功能是最初加进去的,后来改进之后,已经没什么实际意义). exit(退出). menu

Android开发6:Service的使用(简单音乐播放器的实现)

前言 啦啦啦~各位好久不见啦~博主最近比较忙,而且最近一次实验也是刚刚结束~ 好了不废话了,直接进入我们这次的内容~ 在这篇博文里我们将学习Service(服务)的相关知识,学会使用 Service 进行后台工作, 学会使用 Service 与 Activity 进行通信,并在此知识基础上学会使用 MediaPlayer和简单的多线程编程.使用 Handle 更新 UI,并设计成功一个简单的音乐播放器. 是不是很高大上呢~一起来学习~ 基础知识 Service作为Android四大组件之一,在每

iOS 简单音乐播放器 界面搭建

如图搭建一个音乐播放器界面,具备以下几个简单功能: 1,界面协调,整洁. 2,点击播放,控制进度条. 3.三收藏歌曲,点击收藏,心形收藏标志颜色加深. 4,左右按钮,切换歌曲图片和标题. 5,点击中间图片,隐藏所有按钮,仅显示蓝色背景. 设计的整体思路: 1.在搭建界面的时候,为了整洁和方便后续的功能的添加,需要将整个的界面划分为几个部分: ①:最上面的一行包括:一个返回按钮.一个歌曲名称.一个收藏按钮: ②:第二行:一个slider控件.两侧是当前的歌曲播放进度和歌曲的总时长--两个lable

C#简单音乐播放器ListBox歌单列表

简单的音乐播放器实现其实并不难,直接用axWindowsmediaplayer来做,这里没有什么技术含量的,但是axWindowsmediaplayer是不会生成歌单列表的,也就是说,在每次添加音乐后axWindowsmediaplayer是没有记录的,那么我就来简单的做下歌单列表. axWindowsmediaplayer的工作原理其实就是根据Path来加载的,在写歌单时我们需要先来做两件事,1.存储歌曲Path 2.存储歌曲名字 这里暂且不考虑数据库,我使用IO操作通过txt文件来存储这两种