原创

安卓开发之音乐播放器的核心操作以及代码详解

大家很多的android开发者都知道,音乐播放器用的多但是却开发难,难就难在它包含的安卓的四大组件的所以组件还有就是逻辑难,今天我就系统的给大家分析讲解一下音乐播放器的开发流程以及用到的知识点。


1)内容提供者: 这是安卓的四大组件之一主要的用途在于两个APP间的通信,它的作用就在于获取手机中的MP3文件,以保障我们的音乐源。

2)服务:这也是安卓的四大组件之一 主要用于在音乐播放器的后台播放,因为音乐播放器是主页面消失的时候但是后台的音乐会继续执行,再没有销毁页面的时候会一直执行这就符合服务。

3)单例模式:这个的作用在于因为音乐播放器会通常两个页面主页面和一个炫酷的播放音乐界面 使用单例模式是为了让两个页面的歌曲的唯一性不会出现两个页面播放不同的歌曲这种情况。

4)广播:这个是为了给各个页面发送数据更新ui来使用的。

5)数据库:这个的作用主要用于我喜欢 我的歌曲这种页面的相关操作。


首先给大家吧内容提供者获取手机MP3歌曲的代码做一个演示:

public class MusicUtils
{
    public static List<Song> getMusicData(Context context)
    {
        List<Song> list = new ArrayList<Song>();
        // 媒体库查询语句(写一个工具类MusicUtils)
        Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null,
                null, MediaStore.Audio.AudioColumns.IS_MUSIC);
        if (cursor != null) {
            while (cursor.moveToNext()) {
                Song song = new Song();
                song.song = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
                song.singer = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
                song.path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
                song.duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
                song.size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
                if (song.size > 1000 * 800) {
                    // 注释部分是切割标题,分离出歌曲名和歌手 (本地媒体库读取的歌曲信息不规范)
                    if (song.song.contains("-")) {
                        String[] str = song.song.split("-");
                        song.singer = str[0];
                        song.song = str[1];
                    }
                    list.add(song);
                }
            }
            // 释放资源
            cursor.close();
        }
        return list;
    }
    /**
     * 定义一个方法用来格式化获取到的时间
     */
    public static String formatTime(int time) {
        if (time / 1000 % 60 < 10) {
            return time / 1000 / 60 + ":0" + time / 1000 % 60;
        } else {
            return time / 1000 / 60 + ":" + time / 1000 % 60;
        }
    }
}


                         服务和发送广播的相关代码

                         public class MySevers extends Service {
    private Context context;
    private MyTime myTime = new MyTime();
    private Timer timer = new Timer();
    private MediaPlayer mediaPlayer;
    private String key;
    private int dunr;
    private int cutr;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        key = intent.getStringExtra("key");
        timer.schedule(myTime, 200, 200);
        return new MyBinder();
    }
    //开始播放
    public void playMusic() {
        if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
            mediaPlayer.start();
        }
    }
    public void lon(int s) {
    }
    public class MyBinder extends Binder {
        public MySevers getSevers() {
            return MySevers.this;
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
    }
    //点击listView 播放的方法
    public void statelistMusic(String uri) {
        if (mediaPlayer != null) {
            mediaPlayer.pause();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        mediaPlayer = mediaPlayer.create(this, Uri.parse(uri));
        mediaPlayer.start();
    }
   //下一曲的方法
    public void NextlistMusic(int xb) throws IOException {
        if (mediaPlayer != null) {
            mediaPlayer.pause();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        String path = MusicUtils.getMusicData(context).get(xb).path;
        mediaPlayer = mediaPlayer.create(this, Uri.parse(path));
        mediaPlayer.prepare();
        mediaPlayer.start();
    }
//启动音乐
    public void startmusic(int xb) {
        if (mediaPlayer == null) {
            String path = MusicUtils.getMusicData(context).get(xb).path;
            mediaPlayer.create(context, Uri.parse(path));
        } else {
            mediaPlayer.prepareAsync();
            mediaPlayer.start();
        }
    }
    public void pusemusic() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        }
    }
    //暂停
    //判断是不是暂停的状态
    private void puseMusc() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
    //判断是否已经播放
    public boolean getiaPlayer() {
        if (mediaPlayer != null) {
            return mediaPlayer.isPlaying();
        }
        return false;
    }
    class MyTime extends TimerTask
    {
        @Override
        /*发送歌曲的最大长度 以及当前长度  发送1
           和2的作用是为了判断当前的音乐是播放状态还是
           暂停状态以便于更新UI
          */
        public void run() {
            if (mediaPlayer != null) {
                Intent inn = new Intent("com.example.hellomusic.MainActivity.Guangbo");
                Intent innt = new Intent("com.example.hellomusic.Playing.Guangbo");
                dunr = mediaPlayer.getDuration();
                cutr = mediaPlayer.getCurrentPosition();
                inn.putExtra("dunr", dunr);
                inn.putExtra("cutr", cutr);
                if (mediaPlayer.isPlaying()) {
                    inn.putExtra("opee", 1);
                    innt.putExtra("op", 1);

                } else {
                    inn.putExtra("opee", 2);
                    innt.putExtra("op", 2);
                }
                sendBroadcast(inn);
                sendBroadcast(innt);
            }
        }
    }
   //这个的作用是赋空的操作  主要是解决线程的生命周期异常的处理
    public void kong() {
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
        } else {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            mediaPlayer.reset();
        }
    }
    //这个是实现 进度条的点击到哪 唱哪里的歌的一个方法的传值
    public  void getlong(int i)
    {
        mediaPlayer.seekTo(i);
    }
}

                                 单例模式的相关代码

                                 public class Severss
{
    //单利对象
    private static Severss severss;
    private MySevers mySevers;
    private Context context;
    private Intent intent;
    private int xb;
    //Myseverconnect 的对象
    private MySeverConect mySeverConect;
    public  void setContext(Context context)
    {
        this.context = context;
    }
    //空构造
    private Severss()
    {
    }
    //返回单利的对象
    public  static Severss getSeverss()
    {
        if(severss==null)
        {
           severss = new Severss();
        }
        return  severss;
    }
    class MySeverConect implements ServiceConnection
    {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder)
        {
            MySevers.MyBinder myBinder = (MySevers.MyBinder) iBinder;
            mySevers = myBinder.getSevers();
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName)
        {
        }
    }
    //绑定服务
    public void bindsever()
    {
        if (mySeverConect!=null)
        {
        }
        else
        {
            intent = new Intent(context,MySevers.class);
            mySeverConect = new MySeverConect();
            context.bindService(intent,mySeverConect,context.BIND_AUTO_CREATE);
        }
    }
    //解绑服务
    public void stopserver(){
        context.stopService(intent);
    }
    //返回上下
    public Context getContext() {
        return context;
    }
    //返回服务对象
    public MySevers getService()
    {
        return mySevers;
    }
}

                                        广播接受者的相关
                                        
                                        
class Guangbo extends BroadcastReceiver

    {

        private int dunr;

        private int cutr;

        @Override

        public void onReceive(Context context, Intent intent)

        {

            int bl = MyAdate_lb.bl;

            int qq = intent.getIntExtra("yy",bl);

            String songg = MusicUtils.getMusicData(MainActivity.this).get(bl).song;

            String sing = MusicUtils.getMusicData(MainActivity.this).get(bl).singer;

            MainActivity.song.setText(songg);//根据广播发送来的数据更新ui实现歌曲播放到哪 进度条更新到哪的效果

            MainActivity.singer.setText(sing);

            dunr = intent.getIntExtra("dunr",0);

            cutr = intent.getIntExtra("cutr",0);

            seekBar.setMax(dunr);

            seekBar.setProgress(cutr);

            int opee = intent.getIntExtra("opee", 0);//判断当前的播放状态

            if (opee==1)

            {

                bf.setVisibility(View.VISIBLE);

                zt.setVisibility(View.GONE);

            }

            else if (opee==2)

            {

                zt.setVisibility(View.VISIBLE);

                bf.setVisibility(View.GONE);

            }

        }

    } 

                                进度条的滑动到哪播放到哪的操作
 seekBar = (SeekBar) findViewById(R.id.jindu);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                s = i;
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar)
            {
               Severss.getSeverss().getService().getlong(s);
            }
        });

 

效果图的展示:

tu4.jpg图2.jpg

图1.jpgtu3.jpg

希望今天的分享对大家有帮助有喜欢安卓开发的小姐姐可以加我的QQ721882331一起学习一起进步。

关注下方微信公众号“Java精选”(w_z90110),回复关键字领取资料:如HadoopDubboCAS源码等等,免费领取资料视频和项目。 

涵盖:程序人生、搞笑视频、算法与数据结构、黑客技术与网络安全、前端开发、Java、Python、Redis缓存、Spring源码、各大主流框架、Web开发、大数据技术、Storm、Hadoop、MapReduce、Spark、elasticsearch、单点登录统一认证、分布式框架、集群、安卓开发、iOS开发、C/C++、.NET、Linux、Mysql、Oracle、NoSQL非关系型数据库、运维等。

评论

  1. #1

    假诗人 (2017/10/23 14:11:55)回复
    看最新的赛贝尔曲线 https://blog.yoodb.com/fakepoets/article/detail/1456

  2. #2

    假诗人 (2017/09/14 11:46:27)回复
    安卓还好,主要就是学习控件以及逻辑要好。

    嘟嘟 (2017/10/09 14:18:40)回复
    看完才知道是谁写的,不错不错,继续努力。

    路人甲 (2017/09/14 11:46:26)回复
    Android 确实是个不错的开源项目,音乐播放器现在都很流行!

  3. #3

    卐追求卓绝卍 (2017/09/14 11:36:09)回复
    安卓太神奇,看不懂

分享:

支付宝

微信