Android Studio 1-18 使用MediaPlayer完成音乐播放器

Android Studio 1-18 使用MediaPlayer完成音乐播放器

布局

activty布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/lv_main"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9">

    </ListView>

    <SeekBar
        android:id="@+id/seek_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <Button
            android:id="@+id/prev_song"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="上一首" />

        <Button
            android:id="@+id/pause_And_Restart"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="暂停/继续" />

        <Button
            android:id="@+id/next_song"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="下一首" />

        <Button
            android:id="@+id/song_mode"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="模式" />

    </LinearLayout>


</LinearLayout>

listview 布局

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

    <!--<ImageView-->
        <!--android:id="@+id/iv_cover"-->
        <!--android:layout_width="wrap_content"-->
        <!--android:layout_height="wrap_content"-->
        <!--android:src="@mipmap/ic_launcher" />-->

    <TextView
        android:id="@+id/tv_song"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="歌曲名"
        android:textSize="20sp" />

    <RelativeLayout
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

        <TextView
            android:id="@+id/tv_singer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_gravity="bottom"
            android:text="歌手"
            android:textSize="15sp" />

        <TextView
            android:id="@+id/tv_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="时长"
            android:textSize="15sp" />

    </RelativeLayout>

</LinearLayout>

通知 布局

<?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">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/info_prev_song"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="上一首" />

        <Button
            android:id="@+id/info_pause_And_Restart"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="暂停/继续" />

        <Button
            android:id="@+id/info_next_song"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="下一首" />

    </LinearLayout>

</LinearLayout>

java代码

activity

package com.example.day19ex;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.Toast;

import com.example.day19ex.Util.MusicUtils;
import com.example.day19ex.adapter.AdapterList;
import com.example.day19ex.entity.Song;
import com.example.day19ex.provider.MyReceiver;
import com.example.day19ex.service.MusicService;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    private ListView lvMain;
    private static SeekBar seek_main;
    private Button prevSong, pauseAndRestart, nextSong, songMode;

    private static MusicService.MusicBinder musicBinder;
    private ServiceConnection connection;
    private AdapterList adapterList;
    private List<Song> songList;
    private MyReceiver myReceiver;
    private Timer timer = new Timer();

    //默认为顺序播放模式
    private int playMode = Song.MODE_ORDE;

    public static Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == 888) {
                seek_main.setMax(msg.arg2);
                seek_main.setProgress(msg.arg1);
            } else if (msg.what == 110) {
                musicBinder.callPause();
            } else if (msg.what == 120) {
                musicBinder.callPause();
            } else if (msg.what == 130) {
                musicBinder.callPerv();
            } else if (msg.what == 140) {
                musicBinder.callNext();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        intitView();

        //动态注册一个广播
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.notify.pause");
        intentFilter.addAction("com.notify.restart");
        intentFilter.addAction("com.notify.next");
        intentFilter.addAction("com.notify.nav");
        myReceiver = new MyReceiver();
        registerReceiver(myReceiver, intentFilter);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 8848);
        }

        songList = MusicUtils.getMusicData(this);
        adapterList = new AdapterList(this, songList);
        lvMain.setAdapter(adapterList);

        lvMain.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                musicBinder.callPlay(i);
                seek_main.setMax(Integer.parseInt(songList.get(i).getDuration()));
            }
        });

        Intent intent = new Intent(this, MusicService.class);
        startService(intent);

        connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

                musicBinder = (MusicService.MusicBinder) iBinder;

            }

            @Override
            public void onServiceDisconnected(ComponentName componentName) {

            }
        };
        bindService(intent, connection, Service.BIND_AUTO_CREATE);

        seek_main.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, final int i, boolean b) {
                if (b) {
                    musicBinder.callSeek(i);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

    }

    private void intitView() {
        lvMain = (ListView) findViewById(R.id.lv_main);
        prevSong = (Button) findViewById(R.id.prev_song);
        pauseAndRestart = (Button) findViewById(R.id.pause_And_Restart);
        nextSong = (Button) findViewById(R.id.next_song);
        seek_main = findViewById(R.id.seek_main);
        songMode = (Button) findViewById(R.id.song_mode);

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 8848 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

        } else {
            Toast.makeText(this, "必须同意才行", Toast.LENGTH_SHORT).show();
        }
    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.prev_song:
                musicBinder.callPerv();
                break;
            case R.id.pause_And_Restart:
                musicBinder.callPause();
                break;
            case R.id.next_song:
                musicBinder.callNext();
                break;
            case R.id.song_mode:
                int i = playMode % 3;
                musicBinder.callMode(i);
                playMode++;
                switch (i) {
                    case Song.MODE_SINGER:
                        songMode.setText("单曲循环");
                        break;
                    case Song.MODE_ORDE:
                        songMode.setText("顺序播放");
                        break;
                    case Song.MODE_RANDOM:
                        songMode.setText("随机播放");
                        break;

                    default:
                }
                break;


            default:
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myReceiver);
        unbindService(connection);
    }

}

adapter

package com.example.day19ex.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.day19ex.R;
import com.example.day19ex.entity.Song;

import java.util.List;

public class AdapterList extends BaseAdapter {

    private Context context;
    private List<Song> songList;
    private LayoutInflater layoutInflater;

    public AdapterList(Context context, List<Song> songList) {
        this.context = context;
        this.songList = songList;
        layoutInflater = LayoutInflater.from(context);
    }


    @Override
    public int getCount() {
        return songList.size();
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHoder viewHoder;
        if (view == null) {

            view = layoutInflater.inflate(R.layout.layout_item, null, false);
            viewHoder = new ViewHoder();
            viewHoder.song = view.findViewById(R.id.tv_song);
            viewHoder.singer = view.findViewById(R.id.tv_singer);
            viewHoder.duration = view.findViewById(R.id.tv_time);

            view.setTag(viewHoder);
        } else {
            viewHoder = (ViewHoder) view.getTag();
        }

        // 给控件赋值
//        String string_song = songList.get(i).getSong();
//        if (string_song.length() >= 5
//                && string_song.substring(string_song.length() - 4,
//                string_song.length()).equals(".mp3")) {
//            viewHoder.song.setText(string_song.substring(0,
//                    string_song.length() - 4).trim());
//        } else {
//            viewHoder.song.setText(string_song.trim());
//        }

        viewHoder.song.setText(songList.get(i).getTitle());
        viewHoder.singer.setText(songList.get(i).getArtist());
        viewHoder.duration.setText(songList.get(i).getDuration());

        return view;
    }

    private class ViewHoder {
        private TextView song;/*歌曲名*/
        private ImageView cover;/*封面*/
        private TextView singer;/*歌手名*/
        private TextView duration;/*总时长*/
        private TextView position;/*序号*/
    }
}

Util

package com.example.day19ex.Util;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;

import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;

import com.example.day19ex.entity.Song;

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

public class MusicUtils {

    private static final String TAG = "MusicUtils";
    private static int index = 0;

    public static List<Song> getMusicData(Context context) {

        List<Song> songList = new ArrayList<>();
        Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        ContentResolver contentResolver = context.getContentResolver();

        Cursor cursor = contentResolver.query(uri, null, null, null, null);
        if (cursor != null) {
            while (cursor.moveToNext()) {
                String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
                String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
                String duration = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
                String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
                String size = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE));


                index++;
                Song song = new Song(title, artist, duration, data, size, index);
                Log.i(TAG, "getMusicData: "+title+"---"+index);
                songList.add(song);
            }
            cursor.close();
            return songList;
        }else {
            Toast.makeText(context, "没有数据", Toast.LENGTH_SHORT).show();
        }

        return null;
    }

    /*格式化时间的方法*/
    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;
        }

    }

}

Service

package com.example.day19ex.service;


import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import androidx.annotation.RequiresApi;

import com.example.day19ex.MainActivity;
import com.example.day19ex.R;
import com.example.day19ex.Util.MusicUtils;
import com.example.day19ex.entity.Song;

import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class MusicService extends Service {

    private static final String TAG = "MusicService";

    private MediaPlayer player;
    private List<Song> songList;

    private int index;
    private Timer timer;
    //默认是顺序播放
    private int playMode = Song.MODE_ORDE;

    private Notification.Builder builder;

    public MusicService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        player = new MediaPlayer();
        songList = MusicUtils.getMusicData(this);
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        builder = new Notification.Builder(this);
        builder.setSmallIcon(R.mipmap.ic_launcher);

        //自定义广播中的布局
        RemoteViews views = new RemoteViews(getPackageName(), R.layout.layout_inform);

        //第一个按钮的点击逻辑
        /**
         * 通过一个PendingIntent 发送一个intent.
         * getBroadcast的方法是跳往广播的一个intent.
         * getBroadcast的参数,1,上下文,2是请求码唯一即可,3,intent对象,4,PendingIntent的创建方式.
         * setOnClickPendingIntent.这个方法可以给组件设置一个点击事件.参数:1,组件id,2pendingIntent对象
         * 也就是点击以后要跳转到何方.
         */
        Intent intent1 = new Intent();
        intent1.setAction("com.notify.pause");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 800, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.info_pause_And_Restart, pendingIntent);

        Intent intent2 = new Intent();
        intent2.setAction("com.notify.restart");
        PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this, 810, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.info_pause_And_Restart, pendingIntent2);

        Intent intent3 = new Intent();
        intent1.setAction("com.notify.nav");
        PendingIntent pendingIntent3 = PendingIntent.getBroadcast(this, 820, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.info_prev_song, pendingIntent3);

        Intent intent4 = new Intent();
        intent1.setAction("com.notify.next");
        PendingIntent pendingIntent4 = PendingIntent.getBroadcast(this, 830, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.info_next_song, pendingIntent4);

        //设置通知的布局
        builder.setCustomContentView(views);
        //开始一个前台服务
        startForeground(1, builder.build());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new MusicBinder();
    }

    public class MusicBinder extends Binder {
        public void callPlay(int position) {
            play(position);
            index = position;
        }

        public void callPause() {
            pause();
        }

        public void callNext() {
            next();
        }

        public void callPerv() {
            perv();
        }

        public void callSeek(int position) {
            setSeekBar(position);
        }

        public void callMode(int mode) {
            playMode(mode);
        }
    }

    //服务中的一个播放方法
    private void play(final int position) {
        if (timer != null) {
            timer.cancel();
        }

        if (player.isPlaying()) {
            player.stop();
        }
        player.reset();
        try {
            player.setDataSource(songList.get(position).getData());
            player.prepareAsync();
            player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(final MediaPlayer mediaPlayer) {
                    mediaPlayer.start();
                    timer = new Timer();

                    timer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            Message obtain = Message.obtain();
                            obtain.what = 888;
                            obtain.arg1 = mediaPlayer.getCurrentPosition();
                            obtain.arg2 = Integer.parseInt(songList.get(position).getDuration());
                            MainActivity.handler.sendMessage(obtain);
                        }
                    }, 0, 1000);

                }
            });

            //播放完一首歌时的监听/
            player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    selectMode(playMode);
                }
            });

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //进入时确定模式
    public void playMode(int mode) {
        switch (mode) {
            case Song.MODE_SINGER:
                playMode = Song.MODE_SINGER;
                break;
            case Song.MODE_ORDE:
                playMode = Song.MODE_ORDE;
                break;
            case Song.MODE_RANDOM:
                playMode = Song.MODE_RANDOM;
                break;
            default:
        }
    }

    //选择模式的方法
    private void selectMode(int mode) {
        switch (mode) {
            case Song.MODE_SINGER:
                player.setLooping(true);
                play(index);
                playMode = Song.MODE_SINGER;
                break;
            case Song.MODE_ORDE:
                next();
                playMode = Song.MODE_ORDE;
                break;
            case Song.MODE_RANDOM:
                int i = new Random().nextInt(songList.size());
                play(i);
                index = i;
                playMode = Song.MODE_RANDOM;
                break;
            default:
        }
    }

    private void pause() {
        if (player.isPlaying()) {
            player.pause();
        } else {
            player.start();
        }
    }

    private void next() {
        if (++index > songList.size() - 1) {
            index = 0;
        }
        play(index);
    }

    private void perv() {
        if (--index < 0) {
            index = songList.size() - 1;
        }
        play(index);
    }

    private void setSeekBar(int position) {
        player.seekTo(position);
    }

}

provider

package com.example.day19ex.provider;

import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;

import com.example.day19ex.MainActivity;
import com.example.day19ex.R;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals("com.notify.pause")){
            MainActivity.handler.sendEmptyMessage(110);
        }else if(action.equals("com.notify.restart")){
            MainActivity.handler.sendEmptyMessage(120);
        }else if(action.equals("com.notify.nav")){
            MainActivity.handler.sendEmptyMessage(130);
        }else if(action.equals("com.notify.next")){
            MainActivity.handler.sendEmptyMessage(140);
        }

    }
}

entity

package com.example.day19ex.entity;

public class Song {

    public static final int MODE_SINGER = 0 ;//单曲循环
    public static final int MODE_ORDE = 1 ;//顺序播放
    public static final int MODE_RANDOM = 2 ;//随机播放

    /**
     * 歌手
     */
    private String title;
    /**
     * 歌曲名
     */
    private String artist;
    /**
     * 歌曲的地址
     */
    private String duration;
    /**
     * 歌曲长度
     */
    private String data;
    /**
     * 歌曲的大小
     */
    private String size;
    /**
     * 当前歌曲在list中的位置
     */
    private int position;

    /**
     * 封面
     */
    private int cover;

    public Song() {
    }

    public Song(String title, String artist, String duration, String data, String size, int position) {
        this.title = title;
        this.artist = artist;
        this.duration = duration;
        this.data = data;
        this.size = size;
        this.position = position;
    }

    @Override
    public String toString() {
        return "Song{" +
                "title='" + title + '\'' +
                ", artist='" + artist + '\'' +
                ", duration='" + duration + '\'' +
                ", data='" + data + '\'' +
                ", size='" + size + '\'' +
                ", position=" + position +
                ", cover=" + cover +
                '}';
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getDuration() {
        return duration;
    }

    public void setDuration(String duration) {
        this.duration = duration;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }

    public int getCover() {
        return cover;
    }

    public void setCover(int cover) {
        this.cover = cover;
    }
}
发布了20 篇原创文章 · 获赞 4 · 访问量 899

猜你喜欢

转载自blog.csdn.net/v1141261428/article/details/100024917
今日推荐