1. 程式人生 > >Mediaplayer實現音樂播放器,支援後臺播放

Mediaplayer實現音樂播放器,支援後臺播放

mediaplayer是Android開發中常見的播放音訊檔案的類。這個demo主要實現掃描本地的mp3音訊檔案並支援後臺播放,廢話不多說,直接上程式碼

1,佈局檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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"
    android:orientation="vertical"
    tools:context=".ui.activity.MusicActivity"
    android:fitsSystemWindows="true">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#2aa0fa"
        android:padding="10dp">
        <TextView
            android:id="@+id/tv_back"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/back"
            android:drawablePadding="6dp"
            android:text="返回"
            android:textColor="#fff"
            android:textSize="22sp"/>
    </RelativeLayout>
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <LinearLayout
        android:layout_gravity="center_vertical"
        android:padding="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#2aa0fa">
        <LinearLayout
            android:layout_width="0dp"
            android:layout_weight="3"
            android:orientation="vertical"
            android:layout_height="match_parent">
            <TextView
                android:textSize="16sp"
                android:text="帶你去旅行"
                android:singleLine="true"
                android:textColor="#fff"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:marqueeRepeatLimit="marquee_forever"
                android:ellipsize="marquee"
                android:scrollHorizontally="true"
                android:focusableInTouchMode="true"
                android:focusable="true"
                android:id="@+id/playSong"/>
            <TextView
                android:id="@+id/playName"
                android:textSize="14sp"
                android:textColor="#f0f0f0"
                android:text="校長"
                android:singleLine="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
        <ImageView
            android:paddingLeft="10dp"
            android:id="@+id/preview"
            android:layout_width="0dp"
            android:layout_weight="2"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_skip_previous_white_48dp"/>
        <ImageView
            android:id="@+id/pause"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:src="@drawable/uamp_ic_pause_white_48dp"
            android:layout_centerInParent="true"/>
        <ImageView
            android:id="@+id/next"
            android:layout_weight="2"
            android:paddingRight="10dp"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_skip_next_white_48dp"
            android:layout_alignParentRight="true"/>
    </LinearLayout>
</LinearLayout>


2,播放的類musicactivity


public class MusicActivity extends Activity implements AdapterView.OnItemClickListener, View.OnClickListener {
    private static final String TAG = MusicActivity.class.getName();
    private bindServiceConn mConn;
    private ListView mListView;
    private static TextView mPlaySong;
    private static TextView mPlayName;
    private static ImageView mPause;
    private static Bitmap mPauseBitmap;
    private static Bitmap mPlayBitmap;
    private static ArrayList<SongBean> mList;
    private IMusicService mService;
    private int mCurrentPosition = -1;
    public static final int PLAY_MUSIC = 1;
    public static final int PAUSE_MUSIC = 2;
    public static final int PREVIOUS_MUSIC = 3;
    public static final int NEXT_MUSIC = 4;
    private static SharedPreferences sp;
    public static Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case PLAY_MUSIC:
                    int position = msg.arg1;
                    SongBean songBean = mList.get(position);
                    mPlaySong.setText(songBean.getTitle());
                    mPlayName.setText(songBean.getArtist());
                    sp.edit().putString("song", songBean.getTitle()).apply();
                    sp.edit().putString("artist", songBean.getArtist()).apply();
                    sp.edit().putInt("position", position).apply();
                    mPause.setImageBitmap(mPlayBitmap);
                    break;
                case PAUSE_MUSIC:
                    boolean pause = (boolean) msg.obj;
                    if (pause) {
                        mPause.setImageBitmap(mPauseBitmap);
                    } else {
                        mPause.setImageBitmap(mPlayBitmap);
                    }
                    break;
                case PREVIOUS_MUSIC:
                    mPause.setImageBitmap(mPlayBitmap);
                    break;
                case NEXT_MUSIC:
                    mPause.setImageBitmap(mPlayBitmap);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_music);
        StatusBarUtil.setStatusBarColor(this);
        sp = getSharedPreferences("MusicInfo", MODE_PRIVATE);
        Intent intent = new Intent();
        intent.setClass(this, MusicService.class);
        startService(intent);
        mConn = new bindServiceConn();
        bindService(intent, mConn, BIND_AUTO_CREATE);
        initView();
        new musicAsyncTask().execute();
    }
    private void initView() {
        mPauseBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.uamp_ic_play_arrow_white_48dp);
        mPlayBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.uamp_ic_pause_white_48dp);
        mPlaySong = (TextView) findViewById(R.id.playSong);
        mPlayName = (TextView) findViewById(R.id.playName);
        mPause = (ImageView) findViewById(R.id.pause);
        findViewById(R.id.pause).setOnClickListener(this);
        findViewById(R.id.preview).setOnClickListener(this);
        findViewById(R.id.next).setOnClickListener(this);
        mListView = (ListView) findViewById(R.id.listView);
        mListView.setOnItemClickListener(this);
        String song = sp.getString("song", "");
        String artist = sp.getString("artist", "");
        mCurrentPosition = sp.getInt("position", -1);
        mPlaySong.setText(song);
        mPlayName.setText(artist);
        findViewById(R.id.tv_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
    @Override
    public void onClick(View view) {
        if (mList.size() == 0) {
            Toast.makeText(this, getString(R.string.has_no_music_file), Toast.LENGTH_SHORT).show();
            return;
        }
        switch (view.getId()) {
            case R.id.preview:
                mService.previous(mCurrentPosition, mList);
                break;
            case R.id.next:
                mService.next(mCurrentPosition, mList);
                break;
            case R.id.pause:
                mService.pause(mCurrentPosition, mList);
                break;
        }
    }
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        mCurrentPosition = i;
        mPause.setImageBitmap(mPlayBitmap);
        mService.play(mCurrentPosition, mList);
    }
    class bindServiceConn implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mService = (IMusicService) iBinder;
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    }
    class musicAsyncTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mList = new ArrayList<>();
        }
        @Override
        protected Void doInBackground(Void... voids) {
            mList = MediaUtil.getAllSongs(MusicActivity.this);
            return null;
        }
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            Logger.i(TAG, mList.toString());
            mListView.setAdapter(new MusicAdapter(mList));
        }
    }
    class MusicAdapter extends BaseAdapter {
        private ArrayList<SongBean> songList;
        public MusicAdapter(ArrayList<SongBean> songList) {
            this.songList = songList;
        }
        @Override
        public int getCount() {
            return songList == null ? 0 : songList.size();
        }
        @Override
        public Object getItem(int i) {
            return songList.get(i);
        }
        @Override
        public long getItemId(int i) {
            return songList.get(i).getId();
        }
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            viewHolder holder = null;
            if (view == null) {
                view = LayoutInflater.from(MusicActivity.this).inflate(R.layout.item_song_information, null);
                holder = new viewHolder();
                holder.singerName = (TextView) view.findViewById(R.id.singerName);
                holder.songName = (TextView) view.findViewById(R.id.songName);
                view.setTag(holder);
            } else {
                holder = (viewHolder) view.getTag();
            }
            holder.songName.setText(mList.get(i).getTitle());
            holder.singerName.setText(mList.get(i).getArtist());
            return view;
        }
    }
    static class viewHolder {
        public TextView songName;
        public TextView singerName;
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConn);
    }
}


3,定義暫停,播放,上一首,下一首的介面

public interface IMusicService {
    void previous(int position, ArrayList<SongBean> list);
    void pause(int position, ArrayList<SongBean> list);
    void next(int position, ArrayList<SongBean> list);
    void play(int position, ArrayList<SongBean> list);
}


4,支援後臺的service

public class MusicService extends Service {
    private MediaPlayer mPlayer;
    private int currentPosition = -1;
    private boolean isPause = false;

  @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }
    @Override
    public void onCreate() {
        super.onCreate();
        if(mPlayer!=null){
            mPlayer=new MediaPlayer();
        }
    }
    private void playMusic(int position, final ArrayList<SongBean> list) {
        Message message = Message.obtain();
        message.what= MusicActivity.PLAY_MUSIC;
        message.arg1=position;
        MusicActivity.mHandler.sendMessage(message);
        SongBean songBean = list.get(position);
        if (mPlayer == null) {
            mPlayer = new MediaPlayer();
        }
        if (mPlayer.isPlaying()) {
            mPlayer.stop();
            mPlayer = new MediaPlayer();
        }
        try {
            mPlayer.reset();
            mPlayer.setDataSource(songBean.getUrl());
            mPlayer.prepare();
            mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    Log.i("test", "onPrepared");
                    mPlayer.start();
                    isPause = false;
                }
            });
            //音樂播放完成的監聽
            mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    Log.i("test", "onCompletion");
                    currentPosition = currentPosition + 1;
                    if(currentPosition==list.size()){
                        currentPosition=0;
                    }
                    playMusic(currentPosition,list);
                }
            });
            Log.i("test", "duration====" + mPlayer.getDuration());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void callPause(ArrayList<SongBean> list){
        Message message = Message.obtain();
        message.what=MusicActivity.PAUSE_MUSIC;
        if (currentPosition == -1) {
            currentPosition = 0;
            playMusic(currentPosition,list);
        } else if (mPlayer.isPlaying()) {
            mPlayer.pause();
            isPause = true;
        } else {
            mPlayer.start();
            isPause = false;
        }
        message.obj=isPause;
        MusicActivity.mHandler.sendMessage(message);
    }
    public void callPrevious(ArrayList<SongBean> list){
        if (isPause) {
            mPlayer.start();
            Message message = Message.obtain();
            message.what=MusicActivity.PREVIOUS_MUSIC;
            MusicActivity.mHandler.sendMessage(message);
        }
        if (currentPosition == 0) {
            currentPosition = list.size() - 1;
            playMusic(currentPosition,list);
        } else if (currentPosition == -1) {
            currentPosition = 0;
            playMusic(currentPosition,list);
        } else {
            currentPosition = currentPosition - 1;
            playMusic(currentPosition,list);
        }
    }
    public void callNext(ArrayList<SongBean> list){
        if (isPause) {
            mPlayer.start();
            Message message = Message.obtain();
            message.what=MusicActivity.NEXT_MUSIC;
            MusicActivity.mHandler.sendMessage(message);
        }
        if (currentPosition == list.size() - 1) {
            currentPosition = 0;
            playMusic(currentPosition,list);
        } else if (currentPosition == -1) {
            currentPosition = 0;
            playMusic(currentPosition,list);
        } else {
            currentPosition = currentPosition + 1;
            playMusic(currentPosition,list);
        }
    }

    class MyBinder extends Binder implements IMusicService{
        @Override
        public void previous(int position ,ArrayList<SongBean> list) {
            callPrevious(list);
        }
        @Override
        public void pause(int position ,ArrayList<SongBean> list) {
            callPause(list);
        }
        @Override
        public void next(int position,ArrayList<SongBean> list) {
            callNext(list);
        }
        @Override
        public void play(int position, ArrayList<SongBean> list) {
            currentPosition=position;
            playMusic(position,list);
        }
    }

5,獲取本地音訊檔案工具類MediaUtil

public class MediaUtil {
    private static final Uri albumArtUri = Uri.parse("content://media/external/audio/albumart");
    public static ArrayList<SongBean> getAllSongs(Context context) {
        Cursor cursor = context.getContentResolver().query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
                MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        ArrayList<SongBean> mp3Infos = new ArrayList<SongBean>();
        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToNext();
            SongBean mp3Info = new SongBean();
            long id = cursor.getLong(cursor
                    .getColumnIndex(MediaStore.Audio.Media._ID));
            String title = cursor.getString((cursor
                    .getColumnIndex(MediaStore.Audio.Media.TITLE)));
            String artist = cursor.getString(cursor
                    .getColumnIndex(MediaStore.Audio.Media.ARTIST));
            String album = cursor.getString(cursor
                    .getColumnIndex(MediaStore.Audio.Media.ALBUM));
            String displayName = cursor.getString(cursor
                    .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
            long albumId = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
            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 != 0 && displayName.endsWith(".mp3")) {
                mp3Info.setId(id);
                mp3Info.setTitle(title);
                mp3Info.setArtist(artist);
                mp3Info.setAlbum(album);
                mp3Info.setDisplayName(displayName);
                mp3Info.setAlbumId(albumId);
                mp3Info.setDuration(duration);
                mp3Info.setSize(size);
                mp3Info.setUrl(url);
                mp3Infos.add(mp3Info);
            }
        }
        return mp3Infos;
    }
}


6,獲取音樂資訊的songbean

public class SongBean {
    @Override
    public String toString() {
        return "SongBean{" +
                "mId=" + mId +
                ", mTitle='" + mTitle + '\'' +
                ", mArtist='" + mArtist + '\'' +
                ", mAlbum='" + mAlbum + '\'' +
                ", mDisplayName='" + mDisplayName + '\'' +
                ", mAlbumId=" + mAlbumId +
                ", mDuration=" + mDuration +
                ", mSize=" + mSize +
                ", mUrl='" + mUrl + '\'' +
                '}';
    }
    public long getId() {
        return mId;
    }
    private long mId;
    private String mTitle;
    private String mArtist;
    private String mAlbum;
    private String mDisplayName;
    private long mAlbumId;
    private long mDuration;
    private long mSize;
    private String mUrl;
    public void setId(long id) {
        mId = id;
    }
    public void setTitle(String title) {
        mTitle = title;
    }
    public void setArtist(String artist) {
        mArtist = artist;
    }
    public void setAlbum(String album) {
        mAlbum = album;
    }
    public void setDisplayName(String displayName) {
        mDisplayName = displayName;
    }
    public void setAlbumId(long albumId) {
        mAlbumId = albumId;
    }
    public void setDuration(long duration) {
        mDuration = duration;
    }
    public void setSize(long size) {
        mSize = size;
    }
    public void setUrl(String url) {
        mUrl = url;
    }
    public String getTitle() {
        return mTitle;
    }
    public String getArtist() {
        return mArtist;
    }
    public String getAlbum() {
        return mAlbum;
    }
    public String getDisplayName() {
        return mDisplayName;
    }
    public long getAlbumId() {
        return mAlbumId;
    }
    public long getDuration() {
        return mDuration;
    }
    public long getSize() {
        return mSize;
    }
    public String getUrl() {
        return mUrl;
    }
}