天天看点

Android练习项目 Mp3播放器实现(二)

在经过几天的折腾之后,迎来了Mp3播放器的第二篇博客,这篇文章主要将如何实现播放器的播放,下一首,上一首,顺序播放,循环播放,随机播放,单曲循环等操作。

其实操作的过程中主要是通过参数的传递来实现功能的。

在activity里面互相传参有很多中方法,但对于activity和service进行交互有些方法并不适合,通过对Broadcast和BroadcastReceiver等操作,来控制播放的实现。

我们先设定好广播,然后通过发送信号来进行传递数据。

主要在activity里面动态注册广播,通过传递播放的顺序选择,Mp3的url,Mp3播放的位置到service里面,service里面接受传来的广播,获得参数,在进行对应的操作。

还有一个要解决的问题就是,如何通过service将播放的时间和歌曲信息反馈到activity里面,然后更新标题,时间,所以就是参数在service和activity之间进行传递,在程序中通过handle来处理程序的更新数据,通过handle来和activity交互,但由于没有开启线程,所以十分耗时的操作可能不适合,在下一个版本可能需要着手解决这个问题。

所以对于广播的处理就显得比较重要了。

先将作出的效果粘贴出来,目前还没有歌词等处理。

Android练习项目 Mp3播放器实现(二)
Android练习项目 Mp3播放器实现(二)
Android练习项目 Mp3播放器实现(二)
Android练习项目 Mp3播放器实现(二)

对于里面流程的处理十分重要,需要不断的调试,这是最为花费功夫的。

activity_main.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">
<ListView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/listviewmusic">
</ListView>
</LinearLayout>
           

主要功能通过展示listview来显示内容。

自定义子部局:

listmusic.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="60dp"
              android:orientation="vertical">

    <TextView
        android:layout_width="70dp"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="Small Text"
        android:id="@+id/MusicID"
        android:gravity="center"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"/>

    <TextView
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="Small Text"
        android:id="@+id/Musictitle"
        android:textStyle="bold"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/MusicID"
        android:layout_toEndOf="@+id/MusicID"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:textSize="15dp"
        android:singleLine="true"
        android:ellipsize="end"/>

    <TextView
        android:layout_width="220dp"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="Small Text"
        android:id="@+id/MusicArtist"
        android:textColor="#878383"
        android:layout_toRightOf="@+id/MusicID"
        android:layout_toEndOf="@+id/MusicID"
        android:layout_marginLeft="20dp"
        android:layout_below="@+id/Musictitle"
        android:layout_marginTop="7dp"
        android:textSize="12dp"
        android:ellipsize="end"
        android:singleLine="true"/>

    <ImageView
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:id="@+id/MusicIcon"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="30dp"
        />

</RelativeLayout>
           

MainActivity.java

主要获取mp3文件,对于里面出现的Mp3infos这个类,参考我上篇文章,这篇文章没有修改。

package com.flashmusic;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import com.flashmusic.tool.Mp3Info;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class MainActivity extends Activity implements AdapterView.OnItemClickListener {

        //Music的listview控件
        private ListView MusicList;

        // 存储数据的数组列表
        ArrayList<HashMap<String, Object>> MusiclistData = new ArrayList<HashMap<String, Object>>();

        // 适配器
        private SimpleAdapter MusicListAdapter;

        //存放mp3信息
        static  List<Mp3Info> mp3Infos;
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);

                MusicList = (ListView) findViewById(R.id.listviewmusic);

                mp3Infos = getMp3Infos();
                GetData(mp3Infos);

                MusicListAdapter = new SimpleAdapter(
                        this,
                        MusiclistData,
                        R.layout.listmusic,
                        new String[]{"ID", "Title", "Artist", "Icon"},
                        new int[]{R.id.MusicID, R.id.Musictitle, R.id.MusicArtist, R.id.MusicIcon}
                );
                //赋予数据
                MusicList.setAdapter(MusicListAdapter);

                MusicList.setOnItemClickListener(MusiclistListen);
        }

        AdapterView.OnItemClickListener MusiclistListen = new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//                         //Toast.makeText(MainActivity.this, String.valueOf(l), Toast.LENGTH_SHORT).show();
//
//                        //判断当前服务是否已经开启
//                        if(isServiceRunning(getBaseContext(),"com.flashmusic.MusicService")){
//                                stopService(new Intent(MainActivity.this, MusicService.class));
//                        }
//                        Intent intent   = new Intent();
//                        intent.putExtra("url", mp3Infos.get(i).getUrl());
//                        intent.putExtra("position",String.valueOf(i));
//                        intent.setClass(MainActivity.this, MusicService.class);
//                        //启动服务
//                        startService(intent);

                        Intent musicintent      = new Intent(MainActivity.this, MusicActivity.class);
                        //当前播放的位置
                        musicintent.putExtra("position", String.valueOf(i));
                        MusicActivity.mp3Infos = mp3Infos;
                   //     MusicActivity.musicserviceintent = intent;
                        //启动音乐播放界面
                        startActivity(musicintent);
                }
        };

        //判断服务是否存在
        public static boolean isServiceRunning(Context mContext,String className) {
                boolean isRunning = false;
                ActivityManager activityManager = (ActivityManager)
                        mContext.getSystemService(Context.ACTIVITY_SERVICE);
                List<ActivityManager.RunningServiceInfo> serviceList= activityManager.getRunningServices();
                if (!(serviceList.size()>)) {
                        return false;
                }
                for (int i=; i<serviceList.size(); i++) {
                        String a =serviceList.get(i).service.getClassName();
                        if (serviceList.get(i).service.getClassName().equals(className) == true) {
                                isRunning = true;
                                break;
                        }
                }
                return isRunning;
        }
        public void GetData(List<Mp3Info> mp3Infos) {
                for (int i = ; i < mp3Infos.size(); i++) {
                        HashMap<String, Object> map = new HashMap<String, Object>();
                        map.put("ID",mp3Infos.get(i).getID());
                        map.put("Title", mp3Infos.get(i).getTitle());
                        map.put("Artist", mp3Infos.get(i).getArtist());
                        map.put("Icon", R.drawable.musicicon);
                        MusiclistData.add(map);
                }
        }

        public List<Mp3Info> getMp3Infos() {
                Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
                        MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
                int ID = ;
                List<Mp3Info> mp3Infos = new ArrayList<Mp3Info>();
                for (int i = ; i < cursor.getCount(); i++) {
                        Mp3Info mp3Info = new Mp3Info();
                        cursor.moveToNext();
                        long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));   //音乐id,音乐ID不是播放的顺序
                        String title = cursor.getString((cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)));//音乐标题
                        String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));//艺术家
                        long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));//时长
                        long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE));  //文件大小
                        String url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));              //文件路径
                        int isMusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));//是否为音乐
                        if (isMusic != ) {
                                //只把音乐添加到集合当中
                                ID++;
                                mp3Info.setID(ID);
                                mp3Info.setTitle(title);
                                mp3Info.setArtist(artist);
                                mp3Info.setDuration(duration);
                                mp3Info.setSize(size);
                                mp3Info.setUrl(url);
                                mp3Infos.add(mp3Info);
                        }
                }
                return mp3Infos;
        }


        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        }
}

           

musicplay.xml,播放界面的布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:focusable="false"
                android:orientation="horizontal"
                android:background="@drawable/background">


    <TextView
        android:id="@+id/musictitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:textColor="#ffffff"
        android:textSize="20dp"
        android:textStyle="bold"
        android:layout_marginTop="15dp"/>

    <TextView
        android:id="@+id/musicartist"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/musictitle"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="5dp"
        android:textColor="#c6bbbb"/>

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="10dp">

        <ImageView
            android:id="@+id/musicplaymode"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:layout_weight="1"
            android:src="@drawable/orderplay"/>

        <ImageView
            android:id="@+id/musicprevious"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:layout_weight="1"
            android:src="@drawable/musicprevious"/>

        <ImageView
            android:id="@+id/musicplay"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:layout_weight="1"
            android:src="@drawable/musicpause"/>

        <ImageView
            android:id="@+id/musicnext"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:layout_weight="1"
            android:src="@drawable/musicnext"/>

        <ImageView
            android:id="@+id/musicplaymenu"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:layout_weight="1"
            android:src="@drawable/menuplay"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_above="@+id/linearLayout"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/playcurrenttime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/MusicProgress"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:text="00:00"
            android:textAppearance="?android:attr/textAppearanceSmall"/>

        <SeekBar
            android:id="@+id/MusicProgress"
            android:layout_width="184dp"
            android:layout_height="wrap_content"
            android:layout_above="@+id/linearLayout"
            android:layout_toRightOf="@+id/playcurrenttime"
            android:layout_weight="0.16"
            android:indeterminate="false"
            android:max="100"/>

        <TextView
            android:id="@+id/playtime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00:00"
            android:textAppearance="?android:attr/textAppearanceSmall"/>

    </LinearLayout>

</RelativeLayout>
           

接下来就是MusicActivity.java

这里面有个东西我觉得非常好,就是用了static变量,来共享mp3infos文件信息,通过MainActivity函数来赋值进来,相当于不再需要另一块内存来存储数据了,service也是这样实现的,这样每次我们只需要将位置position传进去就能够解决问题了。

package com.flashmusic;

import com.flashmusic.tool.PlayerMSG;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.ThemedSpinnerAdapter;
import android.widget.Toast;

import com.flashmusic.tool.Mp3Info;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.TimeZone;


public class MusicActivity extends Activity implements View.OnClickListener {

    //mp3需要播放的数据
    static List<Mp3Info> mp3Infos;
    static Intent musicserviceintent;

    //播放按钮
    private ImageView MusicPlay;
    //下一首
    private ImageView MusicNext;
    //上一首
    private ImageView MusicPrevious;
    //播放方式选择
    private ImageView MusicMOde;
    //播放菜单
    private ImageView MusicMenu;
    //显示总时间
    private TextView MusicTime;
    //显示当前时间
    private TextView MusicCurrentTime;
    //显示歌曲名
    private TextView MusicTitle;
    //显示歌曲艺术家
    private TextView MusicArtist;
    //进度条
    SeekBar seekBar;
    //广播
    MusicPlayerReceiver musicPlayerReceiver;


    private final int isorderplay = ;//顺序播放
    private final int islistloop = ;//表示列表循环
    private final int isrepeatone = ;//单曲循环
    private final int israndomplay = ;//随机

    public static final String UPDATE_ACTION = "com.flashmusic.action.UPDATE_ACTION";  //更新动作
    public static final String CTL_ACTION = "com.flashmusic.action.CTL_ACTION";        //控制动作
    public static final String MUSIC_CURRENT = "com.flashmusic.action.MUSIC_CURRENT";  //音乐当前时间改变动作
    public static final String MUSIC_DURATION = "com.flashmusic.action.MUSIC_DURATION";//音乐播放长度改变动作
    public static final String MUSIC_PLAYING = "com.flashmusic.action.MUSIC_PLAYING";  //音乐正在播放动作
    public static final String REPEAT_ACTION = "com.flashmusic.action.REPEAT_ACTION";  //音乐重复播放动作
    public static final String SHUFFLE_ACTION = "com.flashmusic.action.RANDOM_ACTION";//音乐随机播放动作
    public static final String PLAY_STATUE = "com.flashmusic.action.PLAY_STATUE";      //更新播放状态

    //是否绑定了对应的service
    Boolean mBound = false;
    //播放方式表识0表示顺序播放,1表示列表循环,2表示单曲循环,3表示随机,初始为顺序播放
    int playmodeflag = ;
    //歌曲播放的位置,就能够获取位置
    int position;
    int currentTime;
    int duration;//总时间

    //记录鼠标点击了几次,播放和暂停状态
    boolean playorpauseflag = false;
    //播放服务
    MusicService mService;
    // 正在播放
    private boolean isPlaying;
    // 暂停
    private boolean isPause;

    //多线程,后台更新UI
    Thread myThread;

    //控制后台线程退出
    boolean playStatus = true;


    //转换毫秒数为时间模式,一般都是分钟数,音乐文件
    public static String formatDuring(long mss) {
        long days = mss / ( *  *  * );
        long hours = (mss % ( *  *  * )) / ( *  * );
        long minutes = (mss % ( *  * )) / ( * );
        long seconds = (mss % ( * )) / ;
        return String.format("%02d", minutes) + ":" + String.format("%02d", seconds);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.musicplay);

        //初始化控件
        InitView();

        //获得传过来的值
        Intent intent = getIntent();
        position = Integer.parseInt(intent.getStringExtra("position"));

        MusicArtist.setText(mp3Infos.get(position).getArtist());
        MusicTitle.setText(mp3Infos.get(position).getTitle());

        //注册广播
        musicPlayerReceiver = new MusicPlayerReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(UPDATE_ACTION);
        filter.addAction(MUSIC_CURRENT);
        filter.addAction(MUSIC_DURATION);
        filter.addAction(PLAY_STATUE);

        registerReceiver(musicPlayerReceiver, filter);


        //设置响应事件
        MusicNext.setOnClickListener(this);
        MusicPrevious.setOnClickListener(this);
        MusicMenu.setOnClickListener(this);
        MusicMOde.setOnClickListener(this);
        MusicPlay.setOnClickListener(this);
        seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
        PlayMusic();
    }

    //初始化控件
    void InitView() {
        MusicPlay = (ImageView) findViewById(R.id.musicplay);
        MusicNext = (ImageView) findViewById(R.id.musicnext);
        MusicPrevious = (ImageView) findViewById(R.id.musicprevious);
        MusicMenu = (ImageView) findViewById(R.id.musicplaymenu);
        MusicMOde = (ImageView) findViewById(R.id.musicplaymode);
        MusicTime = (TextView) findViewById(R.id.playtime);
        MusicCurrentTime = (TextView) findViewById(R.id.playcurrenttime);
        MusicTitle = (TextView) findViewById(R.id.musictitle);
        MusicArtist = (TextView) findViewById(R.id.musicartist);
        seekBar = (SeekBar) findViewById(R.id.MusicProgress);

    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        switch (v.getId()) {
            case R.id.musicplay:
                if (isPlaying) {
                    MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause, null));
                    intent.setClass(MusicActivity.this, MusicService.class);
                    intent.putExtra("MSG", PlayerMSG.MSG.PAUSE_MSG);
                    startService(intent);
                    isPlaying = false;

                } else {
                    MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
                    intent.setClass(MusicActivity.this, MusicService.class);
                    intent.putExtra("MSG", PlayerMSG.MSG.CONTINUE_MSG);
                    startService(intent);
                    isPlaying = true;
                }
                break;
            case R.id.musicplaymode:
                setPlayMOde();
                break;
            case R.id.musicnext:
                PlayNextMusic();
                break;
            case R.id.musicprevious:
                PlayPreviousMusic();
                break;
            case R.id.musicplaymenu:
                break;
            default:
                break;
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    void setPlayMOde() {
        playmodeflag++;
        Intent intent = new Intent(CTL_ACTION);
        intent.putExtra("control", playmodeflag);
        sendBroadcast(intent);
        switch (playmodeflag) {
            case isorderplay:
                MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.orderplay, null));
                break;
            case islistloop:
                MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.repeatplay, null));
                break;
            case isrepeatone:
                MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.repeatoneplay, null));
                break;
            case israndomplay:
                MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.randomplay, null));
                playmodeflag = -;
                break;
            default:
                break;
        }

    }

    SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {

        //停止拖动事件
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            //手动调节进度
            // TODO Auto-generated method stub
            //seekbar的拖动位置
            int progress = seekBar.getProgress();

            ChangeProgress(progress);
            //调用service调节播放进度
            //      mService.setProgress(max, dest);
        }

        //数值改变事件
        @Override
        public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
            // TODO Auto-generated method stub
        }

        //开始拖动事件
        @Override
        public void onStartTrackingTouch(SeekBar arg0) {
            // TODO Auto-generated method stub
        }
    };

    public void ChangeProgress(int progress) {
        Intent intent = new Intent();
        intent.setClass(MusicActivity.this, MusicService.class);
        intent.putExtra("url", mp3Infos.get(position).getUrl());
        intent.putExtra("position", position);
        intent.putExtra("MSG", PlayerMSG.MSG.PROGRESS_CHANGE);
        intent.putExtra("progress", progress);
        startService(intent);
    }

    //播放音乐
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public void PlayMusic() {
        isPlaying = true;

        MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
        // 开始播放的时候为顺序播放
        Intent intent = new Intent();
        intent.setClass(MusicActivity.this, MusicService.class);
        intent.putExtra("url", mp3Infos.get(position).getUrl());
        intent.putExtra("position", position);
        intent.putExtra("MSG", PlayerMSG.MSG.PLAY_MSG);
        MusicService.mp3Infos = mp3Infos;
        startService(intent);
    }

    //播放上一首音乐
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public void PlayPreviousMusic() {
        position = position - ;
        //   MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause,null));

        if (position < ) {
            position = mp3Infos.size() - ;
        }
        Mp3Info mp3Info = mp3Infos.get(position);
        MusicTitle.setText(mp3Info.getTitle());
        MusicArtist.setText(mp3Info.getArtist());
        Intent intent = new Intent();
        intent.setClass(MusicActivity.this, MusicService.class);
        intent.putExtra("url", mp3Info.getUrl());
        intent.putExtra("position", position);
        intent.putExtra("MSG", PlayerMSG.MSG.PRIVIOUS_MSG);
        startService(intent);
        isPlaying = true;

        MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
    }

    //播放下一首音乐
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public void PlayNextMusic() {
        //判断是否是随机播放,因为随机播放设置后,playmodeflag变为-1了
        if (playmodeflag == -) {
            Random random = new Random();
            position = random.nextInt(mp3Infos.size());
        } else
            position = position + ;
        if (position >= mp3Infos.size())
            position = ;

        Mp3Info mp3Info = mp3Infos.get(position);
        MusicTitle.setText(mp3Info.getTitle());
        MusicArtist.setText(mp3Info.getArtist());
        Intent intent = new Intent();
        intent.setClass(MusicActivity.this, MusicService.class);
        intent.putExtra("url", mp3Info.getUrl());
        intent.putExtra("position", position);
        intent.putExtra("MSG", PlayerMSG.MSG.NEXT_MSG);
        startService(intent);
        MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
        isPlaying = true;

    }


    public class MusicPlayerReceiver extends BroadcastReceiver {
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //当前时间更新
            if (action.equals(MUSIC_CURRENT)) {
                currentTime = intent.getIntExtra("currentTime", -);
                seekBar.setProgress(currentTime);
                MusicCurrentTime.setText(formatDuring(currentTime));


            } else if (action.equals(MUSIC_DURATION)) {
                //总时间更新
                duration = intent.getIntExtra("duration", -);
                seekBar.setMax(duration);
                MusicTime.setText(formatDuring(duration));

            } else if (action.equals(UPDATE_ACTION)) {
                position = intent.getIntExtra("position", -);
                String url = mp3Infos.get(position).getUrl();

                MusicTitle.setText(mp3Infos.get(position).getTitle());
                MusicArtist.setText(mp3Infos.get(position).getArtist());
                MusicTime.setText(formatDuring(mp3Infos.get(position).getDuration()));

            } else if (action.equals(PLAY_STATUE)) {
                boolean playstatue = intent.getBooleanExtra("playstatue", true);
                if (playstatue) {
                    MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
                    isPlaying = true;
                } else {
                    MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause, null));
                    isPlaying = false;
                }
            }

        }
    }

    public void onDestroy() {
        //销毁activity时,要记得销毁线程
        playStatus = false;
        super.onDestroy();
    }
}
           

这里面有许多细节,处理的过程就是不断调试。

最为重要的就是写service了,这个里面主要涉及到MP3的播放,暂停,切换,上一首,进行操作的主要是接受MusicActivity里面传过来的广播,然后进行判断,然后处理对应的函数。说的就是这么简单,但处理起来,并不是很好解决。

MusicService.java

package com.flashmusic;

import com.flashmusic.tool.PlayerMSG;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;


import com.flashmusic.tool.Mp3Info;

import java.util.ArrayList;
import java.util.List;

public class MusicService extends Service {

    // mp3的绝对路径
    private String path;
    //当前播放位置
    private int position;
    //当前播放进度
    private int currentTime;

    private int msg;                //播放信息

    private boolean isPause;

    static List<Mp3Info> mp3Infos;    //存放Mp3Info对象的集合

    private int duration;            //播放长度

    int palyflag = ;


    //服务要发送的一些Action
    public static final String UPDATE_ACTION = "com.flashmusic.action.UPDATE_ACTION";  //更新音乐播放曲目
    public static final String CTL_ACTION = "com.flashmusic.action.CTL_ACTION";        //控制播放模式
    public static final String MUSIC_CURRENT = "com.flashmusic.action.MUSIC_CURRENT";  //当前音乐播放时间更新
    public static final String MUSIC_DURATION = "com.flashmusic.action.MUSIC_DURATION";//播放音乐长度更新
    public static final String PLAY_STATUE = "com.flashmusic.action.PLAY_STATUE";      //更新播放状态

    //播放音乐的媒体类
    MediaPlayer mediaPlayer;
    //广播接收器,接收来自MusicActivity的广播
    private MusicReceiver musicReceiver;


    IBinder musicBinder = new MyBinder();

    //handler用来接收消息,来发送广播更新播放时间
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case :
                    if (mediaPlayer != null) {
                        currentTime = mediaPlayer.getCurrentPosition();
                        Intent intent = new Intent();
                        intent.setAction(MUSIC_CURRENT);
                        intent.putExtra("currentTime", currentTime);
                        sendBroadcast(intent); // 给PlayerActivity发送广播
                        mHandler.sendEmptyMessageDelayed(, );
                    }
                    break;
                default:
                    break;
            }
        }

        ;
    };

    class MyBinder extends Binder {
        public Service getService() {
            return MusicService.this;
        }
    }


    @Override
    public void onCreate() {
        super.onCreate();

        mediaPlayer = new MediaPlayer();

        /**
         * 设置音乐播放完成时的监听器
         */
        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
                Intent intent = new Intent(PLAY_STATUE);
                // 发送播放完毕的信号,更新播放状态
                intent.putExtra("playstatue", false);
                sendBroadcast(intent);


                //       Toast.makeText(getApplicationContext(),"服务完成了",Toast.LENGTH_SHORT).show();
                if (palyflag == ) {
                    Intent loopintent = new Intent(PLAY_STATUE);
                    // 发送播放完毕的信号,更新播放状态
                    intent.putExtra("playstatue", true);
                    sendBroadcast(loopintent);
                    // 单曲循环
                    mediaPlayer.start();

                } else if (palyflag == ) {
                    // 列表循环
                    position++;
                    if (position > mp3Infos.size() - ) {
                        //变为第一首的位置继续播放
                        position = ;
                    }
                    Intent sendIntent = new Intent(UPDATE_ACTION);
                    sendIntent.putExtra("position", position);
                    // 发送广播,将被Activity组件中的BroadcastReceiver接收到
                    sendBroadcast(sendIntent);
                    path = mp3Infos.get(position).getUrl();
                    play();
                } else if (palyflag == ) { // 顺序播放
                    position++;    //下一首位置
                    if (position <= mp3Infos.size() - ) {
                        Intent sendIntent = new Intent(UPDATE_ACTION);
                        sendIntent.putExtra("position", position);
                        // 发送广播,将被Activity组件中的BroadcastReceiver接收到
                        sendBroadcast(sendIntent);
                        path = mp3Infos.get(position).getUrl();
                        play();
                    } else {
                        mediaPlayer.seekTo();
                        position = ;
                        Intent sendIntent = new Intent(UPDATE_ACTION);
                        sendIntent.putExtra("position", position);
                        // 发送广播,将被Activity组件中的BroadcastReceiver接收到
                        sendBroadcast(sendIntent);
                    }
                } else if (palyflag == ) {    //随机播放
                    position = getRandomIndex(mp3Infos.size() - );
                    Intent sendIntent = new Intent(UPDATE_ACTION);
                    sendIntent.putExtra("position", position);
                    // 发送广播,将被Activity组件中的BroadcastReceiver接收到
                    sendBroadcast(sendIntent);
                    path = mp3Infos.get(position).getUrl();
                    play();
                }
            }
        });

        musicReceiver = new MusicReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(CTL_ACTION);
        //     filter.addAction(SHOW_LRC);
        registerReceiver(musicReceiver, filter);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        path = intent.getStringExtra("url");        //歌曲路径
        position = intent.getIntExtra("position", -);    //当前播放歌曲的在mp3Infos的位置
        msg = intent.getIntExtra("MSG", );            //播放信息
        if (msg == PlayerMSG.MSG.PLAY_MSG) {    //直接播放音乐
            play();
        } else if (msg == PlayerMSG.MSG.PAUSE_MSG) {    //暂停
            pause();
        } else if (msg == PlayerMSG.MSG.STOP_MSG) {        //停止
            stop();
        } else if (msg == PlayerMSG.MSG.CONTINUE_MSG) {    //继续播放
            resume();
        } else if (msg == PlayerMSG.MSG.PRIVIOUS_MSG) {    //上一首
            previous();
        } else if (msg == PlayerMSG.MSG.NEXT_MSG) {        //下一首
            next();
        } else if (msg == PlayerMSG.MSG.PROGRESS_CHANGE) {    //进度更新
            currentTime = intent.getIntExtra("progress", -);
            play(currentTime);
        } else if (msg == PlayerMSG.MSG.PLAYING_MSG) {
            mHandler.sendEmptyMessage();
        }
        return super.onStartCommand(intent, flags, startId);
    }

    private void play(int currentTime) {
        try {

            mediaPlayer.reset();// 把各项参数恢复到初始状态
            mediaPlayer.setDataSource(path);
            mediaPlayer.prepare(); // 进行缓冲
            mediaPlayer.setOnPreparedListener(new PreparedListener(currentTime));// 注册一个监听器
            //更新播放状态
            Intent intent = new Intent(PLAY_STATUE);
            // 发送播放完毕的信号,更新播放状态
            intent.putExtra("playstatue", true);
            sendBroadcast(intent);
            mHandler.sendEmptyMessage();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //继续播放
    private void resume() {
        if (isPause) {
            mediaPlayer.start();
            isPause = false;
        }
    }

    /**
     * 上一首
     */
    private void previous() {
        Intent sendIntent = new Intent(UPDATE_ACTION);
        sendIntent.putExtra("position", position);
        // 发送广播,将被Activity组件中的BroadcastReceiver接收到
        sendBroadcast(sendIntent);
        play();
    }

    /**
     * 下一首
     */
    private void next() {
        Intent sendIntent = new Intent(UPDATE_ACTION);
        sendIntent.putExtra("position", position);
        // 发送广播,将被Activity组件中的BroadcastReceiver接收到
        sendBroadcast(sendIntent);
        play();
    }

    private void pause() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
            isPause = true;
        }
    }

    private void stop() {
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            try {
                mediaPlayer.prepare(); // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 实现一个OnPrepareLister接口,当音乐准备好的时候开始播放
     */
    private final class PreparedListener implements MediaPlayer.OnPreparedListener {
        private int currentTime;

        public PreparedListener(int currentTime) {
            this.currentTime = currentTime;
        }

        @Override
        public void onPrepared(MediaPlayer mp) {
            mediaPlayer.start(); // 开始播放
            if (currentTime > ) { // 如果音乐不是从头播放
                mediaPlayer.seekTo(currentTime);
            }
            Intent intent = new Intent();
            intent.setAction(MUSIC_DURATION);
            duration = mediaPlayer.getDuration();
            intent.putExtra("duration", duration);    //通过Intent来传递歌曲的总长度
            sendBroadcast(intent);
        }
    }

    protected int getRandomIndex(int end) {
        int index = (int) (Math.random() * end);
        return index;
    }


    public class MusicReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            int control = intent.getIntExtra("control", -);
            switch (control) {
                case :
                    palyflag = ; // 顺序播放
                    break;
                case :
                    palyflag = ;    //列表循环
                    break;
                case :
                    palyflag = ;    //单曲循环
                    break;
                case :
                    palyflag = ;  //随机
                    break;
                default:
                    break;
//            if(action.equals(SHOW_LRC)){
//                current = intent.getIntExtra("listPosition", -1);
//                initLrc();
            }
        }
    }


    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        //当绑定后,返回一个musicBinder
        return musicBinder;
    }

    @Override
    public void onDestroy() {
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }

    }
}
           

这些函数里面有个标识,其实有时候,我们并不想通过new一个类来处理信息,这个就是个很好的表示来解决问题。

PlayerMSG.java

package com.flashmusic.tool;

/**
 * Created by zhouchenglin on 2016/4/18.
 */
public class PlayerMSG {
    public class MSG{
        public static final int PLAY_MSG = ;       //播放
        public static final int PAUSE_MSG = ;      //暂停
        public static final int STOP_MSG = ;       //停止
        public static final int CONTINUE_MSG = ;   //继续
        public static final int PRIVIOUS_MSG = ;   //上一首
        public static final int NEXT_MSG = ;       //下一首
        public static final int PROGRESS_CHANGE = ;//进度改变
        public static final int PLAYING_MSG = ;    //正在播放
    }
}
           

主要的内容就这么多,现在还未完成歌词显示,还有需要解决地问题,就是需要在子线程里面更新UI,这个需要重新考虑。

这篇博客,改变了上一篇博客里面的设计思路,让我掌握了广播的使用。

参考这篇文章,我就是参考大神之后修改的,站在巨人的肩膀上看世界

源码下载

继续阅读