MusicPlayerByService

MusicPlayerByService

MainActivity

package com.hipeak.musicplayerbyservice;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private List<Song> songList;//存放歌曲信息
    private static final int REQUEST_READ_EXTERNAL = 1;//定义读取sd卡空间权限

    private ListView lv;//listView列表
    private ImageView songPicIV;//最近歌曲栏的专辑图片
    private TextView nameTV;//最近歌曲栏的歌曲名
    private ImageView playBtn;//最近歌曲栏的播放按钮

    private int index;//存放最近听的是哪首歌
    private SharedPreferences sp;//轻量型数据

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

        sp = getSharedPreferences("saveSongPlayState", MODE_PRIVATE);

        lv = findViewById(R.id.listView);//listView列表
        songPicIV = findViewById(R.id.songPicIV);//最近歌曲栏的专辑图片
        nameTV = findViewById(R.id.songNameTV);//最近歌曲栏的歌曲名
        playBtn = findViewById(R.id.playBtn);//最近歌曲栏的播放按钮

        requestPermissions();//请求权限并获取歌曲信息
//        Log.d(TAG, "onCreate: songList的长度为===" + songList.size());//测试songList的长度
//        for (int i = 0; i < songList.size(); i++) {//测试songList的内容
//            Log.d(TAG, "onCreate: 测试存入的songList===" + songList.get(i).toString());
//        }

        SongAdapter adapter = new SongAdapter(this, songList);
        lv.setAdapter(adapter);

        //点击最近歌曲的播放按钮进行跳转
        playBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                jumpToAcitivity(index);
            }
        });

        //点击ListView的某一项进行跳转
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                jumpToAcitivity(position);
            }
        });

    }


    @Override
    protected void onResume() {
        super.onResume();
        //从SharePre中获取最近歌曲信息
        getSongState();
        nameTV.setText(songList.get(index).getTitle());//设置最近歌曲的歌名
        songPicIV.setImageBitmap(getAlbumPic(index));//设置最近歌曲的专辑图片
    }


    //跳转到Activity
    private void jumpToAcitivity(int pos) {
        Intent intent = new Intent(MainActivity.this, SongActivity.class);
        Bundle bundle = new Bundle();
        bundle.putInt("pos", pos);
        bundle.putSerializable("list", (Serializable) songList);
        intent.putExtras(bundle);
        startActivity(intent);
    }

    private void requestPermissions() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
//            Log.d(TAG, "走到requestPermissions:的if里了 ");
            getMusic();
        } else {
            ActivityCompat.requestPermissions(this
                    , new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}
                    , REQUEST_READ_EXTERNAL);
//            Log.d(TAG, "走到requestPermissions:的else里了 ");
        }
    }

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_READ_EXTERNAL
                && Manifest.permission.READ_EXTERNAL_STORAGE.equals(permissions[0])
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//            Log.d(TAG, "走到onRequestPermissionsResult:的if里了 ");
            getMusic();
        } else {
            Toast.makeText(this, "您拒绝了读取sd卡的权限", Toast.LENGTH_LONG).show();
//            Log.d(TAG, "走到onRequestPermissionsResult:的else里了 ");
        }
    }


    //获取歌曲信息,并存放到songList中
    private void getMusic() {
        songList = new ArrayList<>();
        ContentResolver resolver = getContentResolver();
        Uri uri = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);//content://media/external/audio/media
//        Log.d("", "uri===" + uri);
        Cursor cursor = resolver.query(uri
                , new String[]{MediaStore.Audio.Media._ID //_id 音频唯一标识
                        , MediaStore.Audio.Media.TITLE //歌曲名称
                        , MediaStore.Audio.Media.ARTIST //歌手名
                        , MediaStore.Audio.Media.DURATION //歌曲时长
                        , MediaStore.Audio.Media.ALBUM//专辑名
                        , MediaStore.Audio.Media.DISPLAY_NAME//文件名
                        , MediaStore.Audio.Media.DATA} //歌曲路径名
                , null, null, null);
//        Log.d("", "cursor count====" + cursor.getCount());
        while (cursor.moveToNext()) {
            String id = cursor.getString(0);//_id 音频唯一标识
            String title = cursor.getString(1);//歌曲名称
            String artist = cursor.getString(2);//歌手名
            int duration = cursor.getInt(3);//歌曲时长,单位毫秒
            String album = cursor.getString(4);//专辑名
            String displayName = cursor.getString(5);//文件名
            String songPathname = cursor.getString(6);//歌曲路径名

            String albumPathname = songPathname.substring(0, 26) + album + ".jpg";//专辑图片路径名
            songList.add(new Song(id, title, artist, duration, album, displayName, songPathname, albumPathname));
        }
        cursor.close();
    }

    //获取专辑图片
    private Bitmap getAlbumPic(int recentlySong) {
//        Log.d(TAG, "getAlbumPic: albumPathname===" + son.getAlbumPathname());//  /storage/emulated/0/Music/我很忙.jpg
        File myFile = new File(songList.get(recentlySong).getAlbumPathname());
        if (myFile.exists()) {
            Bitmap bitmap = BitmapFactory.decodeFile(songList.get(recentlySong).getAlbumPathname());
            return bitmap;
        }
        return null;
    }

    //拿到最近听到哪首歌了
    private void getSongState() {
        if (sp != null) {
            index = sp.getInt("index", 0);
        }
        Log.d(TAG, "get: 读取的值===之前听的是哪首歌:" + index);
    }

}

SongActivity

package com.hipeak.musicplayerbyservice;

import android.animation.ObjectAnimator;
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.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.util.List;

public class SongActivity extends Activity {
    private Button backBtn;//返回键
    private TextView titleName, artistName, albumName;//歌曲名,作者名,专辑名
    private ImageView albumIV;//专辑图片
    private TextView lyricsTV;//歌词
    private TextView currentProgressTV;//当前进度,表示播放到哪里了
    private SeekBar seekBar;//进度条
    private TextView durationLong;//歌曲长度


    private ImageView modeBtn, previousSongBtn, playAndPauseBtn, nextSongBtn;
    private int playOrPause;//0表示正在播放,1表示处在暂停状态

    private int index;//记录当前播放的是拿一首歌
    private int curProgress;//记录当前歌曲播放到多少毫秒了
    private List<Song> songList;//存放歌曲数据

    private static final String TAG = "SongActivity";
    private ServiceConnection conn;//服务连接

    private int playMode = 1;//playMode==1表示列表循环,2表示随机,3表示单曲循环
    private SharedPreferences sp;//轻量型数据
    private RenewReceiver receiver;//广播


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

        sp = getSharedPreferences("saveSongPlayState", MODE_PRIVATE);

        backBtn = findViewById(R.id.backBtn);//返回键
        titleName = findViewById(R.id.titleName);//歌曲名
        artistName = findViewById(R.id.artistName);//作者名
        albumName = findViewById(R.id.albumName);//专辑名
        albumIV = findViewById(R.id.albumIV);//专辑图片
        lyricsTV = findViewById(R.id.lyricsTV);//歌词
        currentProgressTV = findViewById(R.id.currentProgressTV);//当前进度,表示播放到哪里了
        seekBar = findViewById(R.id.seekBar);//进度条
        durationLong = findViewById(R.id.durationLong);//歌曲长度
        modeBtn = findViewById(R.id.modeBtn);//播放模式
        previousSongBtn = findViewById(R.id.previousSongBtn);//上一首
        playAndPauseBtn = findViewById(R.id.playAndPauseBtn);//播放和暂停
        nextSongBtn = findViewById(R.id.nextSongBtn);//下一首

        //拿到数据
        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        index = bundle.getInt("pos");
        songList = (List<Song>) bundle.getSerializable("list");

        //填充数据
        fillTheInterface();

        //个bindService绑定
        doBind();

        //点击playAndPauseBtn按钮进行播放或暂停
        playAndPauseBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //playOrPause;//0表示正在播放,1表示处在暂停状态
                switch (playOrPause) {
                    case 0://当前处于播放状态

                        //要改成什么状态   播放是true 暂停时false
                        playAndPauseBtn.setSelected(false);
                        doStart(index);//播放当前index对应的歌曲
                        playOrPause = 1;
                        break;
                    case 1:
                        playAndPauseBtn.setSelected(true);
                        doPause();
                        playOrPause = 0;
                        break;
                }
            }
        });

        //播放模式(随机、单曲、列表循环)
        modeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switch (playMode) {
                    //playMode==1表示列表循环,2表示随机,3表示单曲循环
                    case 1:
                        modeBtn.setImageResource(R.drawable.suijibofang);
                        playMode = 2;

                        break;
                    case 2:
                        modeBtn.setImageResource(R.drawable.danquxunhuan);
                        playMode = 3;
                        break;
                    case 3:
                        modeBtn.setImageResource(R.drawable.liebiaoxunhuan);
                        playMode = 1;
                        break;
                }
                Log.d(TAG, "onClick: 保存的playMode===" + playMode);
                savePlayMode();//保存当前播放模式,播放歌曲,播放到多少毫秒
            }
        });

        //上一首
        previousSongBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doPreviousSong();
            }
        });

        //下一首
        nextSongBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doNextSong();
            }
        });

        //进入这个页面就开始播放
        doStart(index);//播放当前index对应的歌曲


        //动态注册广播
        receiver = new RenewReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.hipeak.musicplayerbyservice.music");
        registerReceiver(receiver, filter);

        //拖动进度条
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser) {
                    Log.d(TAG, "onProgressChanged: 当前进度===" + progress);
//                    player.seekTo((int) (progress / 100.0 * songList.get(index).getDuration()));
                    Log.d(TAG, "onProgressChanged: 发送的拖动条的毫秒值为===" + (int) (progress / 100.0 * songList.get(index).getDuration()));
                    adjustMusicProgress((int) (progress / 100.0 * songList.get(index).getDuration()));//根据拖动条更新音乐进度

                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        backBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "onClick: 点击返回键退出当前页面===");
                Intent intent1 = new Intent(SongActivity.this, MainActivity.class);
                startActivity(intent1);
                finish();
            }
        });
    }


    /**
     * 旋转图片
     */
    private ObjectAnimator mAnimator;
    private boolean IS_MUSIC_PLAY_PHOTO = false;
    private ImageView isMusicPhoto;

    private void rotateImage(ImageView musicPhoto) {
        if (IS_MUSIC_PLAY_PHOTO) {
            if (musicPhoto != isMusicPhoto) {
                mAnimator = ObjectAnimator.ofFloat(musicPhoto, "rotation", 0.0f, 360.0f);
                isMusicPhoto = musicPhoto;
            }
        } else {
            //旋转动画
            mAnimator = ObjectAnimator.ofFloat(musicPhoto, "rotation", 0.0f, 360.0f);
            isMusicPhoto = musicPhoto;
            IS_MUSIC_PLAY_PHOTO = true;
        }

        //设定转一圈的时间
        mAnimator.setDuration(20000);
        //设定无限循环
        mAnimator.setRepeatCount(Animation.INFINITE);
        // 循环模式
        mAnimator.setRepeatMode(ObjectAnimator.RESTART);
        // 匀速
        mAnimator.setInterpolator(new LinearInterpolator());
        if (mAnimator.isPaused()) {//判断是否暂停
            mAnimator.resume();//继续
        } else {
            //开始动画
            mAnimator.start();
        }

//        mAnimator.reverse();

    }


    //填充界面
    private void fillTheInterface() {
//        lyricsTV = findViewById(R.id.lyricsTV);//歌词
//        currentProgressTV = findViewById(R.id.currentProgressTV);//当前进度,表示播放到哪里了
//        seekBar = findViewById(R.id.seekBar);//进度条

        titleName.setText(songList.get(index).getTitle());//设置歌曲名
        artistName.setText(songList.get(index).getArtist());//设置作者名
        albumName.setText(songList.get(index).getAlbum());//设置专辑名
        albumIV.setImageBitmap(getAlbumPic(index));//设置专辑图片

        int dur = songList.get(index).getDuration() / 1000;
        String durdur = dur % 60 < 10 ?
                dur / 60 + ":0" + dur % 60
                : dur / 60 + ":" + dur % 60;
        durationLong.setText(durdur);//设置歌曲长度

        if (sp != null) {
//            modeBtn.setText(sp.getString("playMode", "列表循环"));//读取上次的播放模式
            Log.d(TAG, "fillTheInterface: 测试sp.getInt(\"playMode\", 1)===" + sp.getInt("playMode", 1));


            playMode = sp.getInt("playMode", 1);//读取上次的播放模式
//            //playMode==1表示列表循环,2表示随机,3表示单曲循环
            switch (playMode) {
                case 1:
                    modeBtn.setImageResource(R.drawable.liebiaoxunhuan);
                    break;
                case 2:
                    modeBtn.setImageResource(R.drawable.suijibofang);
                    break;
                case 3:
                    modeBtn.setImageResource(R.drawable.danquxunhuan);
                    break;
            }
        }

        rotateImage(albumIV);//旋转图片

    }

    //获取专辑图片
    private Bitmap getAlbumPic(int recentlySong) {
//        Log.d(TAG, "getAlbumPic: albumPathname===" + son.getAlbumPathname());//  /storage/emulated/0/Music/我很忙.jpg
        File myFile = new File(songList.get(recentlySong).getAlbumPathname());
        if (myFile.exists()) {
            Bitmap bitmap = BitmapFactory.decodeFile(songList.get(recentlySong).getAlbumPathname());
            return bitmap;
        }
        return null;
    }

    //获取歌词
    private void getLyrics(Song son, String time) {//time是当前的时间,格式为"分钟:秒",例如"00:00"
        int i = 0;
        String basePath = Environment.getExternalStorageDirectory().getPath();
//        Log.d(TAG, "run: basePath===" + basePath);
        File file = new File(basePath + "/Music/" + son.getDisplayName().substring(0, son.getDisplayName().length() - 4) + ".lrc");
//        Log.d(TAG, "getLyrics: file===" + file);

        try {
            FileInputStream fis = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fis, "GBK");
            BufferedReader br = new BufferedReader(isr);
            String content;
            while ((content = br.readLine()) != null) {
                i++;
//                Log.d(TAG, "拿到的/t===i===" + i + "getLyrics: 拿到个歌词为content===" + content);
                if (content.length() > 6 && content.substring(1, 6).equals(time)) {
                    int pos = content.indexOf(']');
                    lyricsTV.setText(content.substring(pos + 1, content.length()));
                    break;
                }
            }
            br.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //绑定Service
    private void doBind() {
        Log.d(TAG, "doBind: ===");
        Intent intent = new Intent(SongActivity.this, PlayService.class);
        if (conn == null) {
            conn = new ServiceConnection() {

                //当与MyService绑定成功时执行这里的方法
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.d(TAG, "onServiceConnected: ===");
                }

                //当与MyService解绑成功时执行这里的方法
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.d(TAG, "onServiceDisconnected: ===");
                }
            };
        }
        Bundle bundle = new Bundle();
        bundle.putSerializable("list", (Serializable) songList);//绑定的时候将songList传过去
        intent.putExtras(bundle);
        //Context.BIND_AUTO_CREATE 绑定的时候,服务不存在,会自动创建
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }

    //解绑
    private void doUnbind() {
        if (conn != null) {
            unbindService(conn);//不能重复调用
            conn = null;
        }
    }

    //播放和继续
    private void doStart(int index) {
        Intent intent = new Intent(this, PlayService.class);
        intent.putExtra("flag", PlayService.FLAG_PLAY);
        intent.putExtra("pos", index);
        startService(intent);
//        playAndPauseBtn.setText("暂停");
        playAndPauseBtn.setSelected(false);
        playOrPause = 1;
        mAnimator.resume();//专辑图片继续旋转
    }

    //暂停
    private void doPause() {
        Intent intent = new Intent(this, PlayService.class);
        intent.putExtra("flag", PlayService.FLAG_PAUSE);
        startService(intent);
        mAnimator.pause();//专辑图片暂停旋转
    }

    //根据拖动条调整音乐进度
    private void adjustMusicProgress(int progress) {
        Intent intent = new Intent(this, PlayService.class);
        intent.putExtra("flag", PlayService.FlAG_PROGRESS);
        intent.putExtra("progress", progress);
        startService(intent);
    }

    //上一首
    private void doPreviousSong() {
        Log.d(TAG, "doPreSong: 播放上一首===");
        switch (playMode) {
            //playMode==1表示列表循环,2表示随机,3表示单曲循环
            case 1:
                index = (index - 1 + songList.size()) % songList.size();
                break;
            case 2:
                int random = (int) (Math.random() * songList.size());//随机出的下一首歌的下标
                index = random;
                Log.d(TAG, "doPreSong: 随机出的下一首歌的下标为===" + random);
                break;
            case 3:
                break;
        }

        titleName.setText("歌曲名:" + songList.get(index).getTitle());
        artistName.setText("歌手名:" + songList.get(index).getArtist());
        albumName.setText("专辑名:" + songList.get(index).getAlbum());

        int dur = songList.get(index).getDuration() / 1000;
        String durdur = dur % 60 < 10 ?
                dur / 60 + ":0" + dur % 60
                : dur / 60 + ":" + dur % 60;
        durationLong.setText(durdur);//设置歌曲长度

        seekBar.setProgress(0);
        currentProgressTV.setText("0:00");

        playAndPauseBtn.setSelected(false);
        playOrPause = 1;

        albumIV.setImageBitmap(getAlbumPic(index));//播放上一首的时候更新图片
        doStart(index);
    }

    //下一首
    private void doNextSong() {
        Log.d(TAG, "doPreSong: 播放下一首===");
        switch (playMode) {
            //playMode==1表示列表循环,2表示随机,3表示单曲循环
            case 1:
                index = (index + 1 + songList.size()) % songList.size();
                break;
            case 2:
                int random = (int) (Math.random() * songList.size());//随机出的下一首歌的下标
                index = random;
                Log.d(TAG, "doPreSong: 随机出的下一首歌的下标为===" + random);
                break;
            case 3:
                break;
        }

        titleName.setText("歌曲名:" + songList.get(index).getTitle());
        artistName.setText("歌手名:" + songList.get(index).getArtist());
        albumName.setText("专辑名:" + songList.get(index).getAlbum());

        int dur = songList.get(index).getDuration() / 1000;
        String durdur = dur % 60 < 10 ?
                dur / 60 + ":0" + dur % 60
                : dur / 60 + ":" + dur % 60;
        durationLong.setText(durdur);//设置歌曲长度

        seekBar.setProgress(0);
        currentProgressTV.setText("0:00");

        playAndPauseBtn.setSelected(false);
        playOrPause = 1;

        albumIV.setImageBitmap(getAlbumPic(index));//播放上一首的时候更新图片
        doStart(index);
    }


    //用SharedPreferences保存当前听的是哪首歌
    private void savePlayMode() {
        SharedPreferences.Editor edit = sp.edit();
        edit.putInt("index", index);//存放当前听的是哪首歌
        edit.putInt("progress", curProgress);//存放当前听到哪了,单位毫秒
        edit.putInt("playMode", playMode);//保存当前播放模式
        edit.apply();
//        Log.d(TAG, "save: 保存的值===当前听的是哪首歌:" + index + "听到第多少毫秒===" + progress);
    }

    //自定义广播类
    public class RenewReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            //当接收到广播时
            curProgress = intent.getIntExtra("curProgress", 0);
//            Log.d(TAG, "onReceive: SongActivity中收到的广播为===" + curProgress);

            if (curProgress == -99) {//收到service发送的播放完毕的广播
                Log.d(TAG, "onReceive: SongActivity收到播放完毕的广播===");
                doNextSong();//接着播放下一首
            }

            int baifenbi = (int) (curProgress * 1.0 / songList.get(index).getDuration() * 100);
            seekBar.setProgress(baifenbi);
//            Log.d(TAG, "onReceive: seekBar的进度===" + seekBar.getProgress());


            int dur = curProgress / 1000;
            String durdur = dur % 60 < 10 ?
                    "0" + dur / 60 + ":0" + dur % 60
                    : "0" + dur / 60 + ":" + dur % 60;
//            Log.d(TAG, "onReceive: 收到的当前时间为===" + durdur);
            currentProgressTV.setText(durdur);
            getLyrics(songList.get(index), durdur);

            savePlayMode();//保存以下当前听到哪首歌了
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: ===");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        doUnbind();//解绑service
        unregisterReceiver(receiver);//注销广播
    }
}

Song

package com.hipeak.musicplayerbyservice;

import java.io.Serializable;

public class Song implements Serializable {
    private String id;//_id
    private String title;//歌曲名称
    private String artist;//歌手名
    private int duration;//歌曲时长
    private String album;//专辑名
    private String displayName;//文件名
    private String songPathname;//歌曲路径名
    private String albumPathname;//专辑图片路径名

    public Song(String id, String title, String artist, int duration, String album, String displayName, String songPathname, String albumPathname) {
        this.id = id;
        this.title = title;
        this.artist = artist;
        this.duration = duration;
        this.album = album;
        this.displayName = displayName;
        this.songPathname = songPathname;
        this.albumPathname = albumPathname;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    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 int getDuration() {
        return duration;
    }

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

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getSongPathname() {
        return songPathname;
    }

    public void setSongPathname(String songPathname) {
        this.songPathname = songPathname;
    }

    public String getAlbumPathname() {
        return albumPathname;
    }

    public void setAlbumPathname(String albumPathname) {
        this.albumPathname = albumPathname;
    }

    @Override
    public String toString() {
        return "Song{" +
                "id='" + id + '\'' +
                ", title='" + title + '\'' +
                ", artist='" + artist + '\'' +
                ", duration=" + duration +
                ", album='" + album + '\'' +
                ", displayName='" + displayName + '\'' +
                ", songPathname='" + songPathname + '\'' +
                ", albumPathname='" + albumPathname + '\'' +
                '}';
    }
}

SongAdapter

package com.hipeak.musicplayerbyservice;

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

import java.util.List;

public class SongAdapter extends BaseAdapter {
    private Context context;
    private List<Song> songList;

    public SongAdapter(Context context, List<Song> songList) {
        this.context = context;
        this.songList = songList;
    }

    @Override
    public int getCount() {
        return songList == null ? 0 : songList.size();
    }

    @Override
    public Object getItem(int position) {
        return songList.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.listview_item, null);
            viewHolder.name = convertView.findViewById(R.id.songNameTV);
            viewHolder.ablum = convertView.findViewById(R.id.albumNameTV);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        Song song = songList.get(position);
        viewHolder.name.setText(song.getTitle());
        viewHolder.ablum.setText(song.getAlbum());

        return convertView;
    }

    private class ViewHolder {
        private TextView name;
        private TextView ablum;
    }
}

PlayService

package com.hipeak.musicplayerbyservice;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

import java.io.File;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class PlayService extends Service {
    private static final String TAG = "MyService";
    public static final int FLAG_PLAY = 1;//播放
    public static final int FLAG_PAUSE = 2;//暂停
    public static final int FlAG_PROGRESS = 3;//更新进度
    private List<Song> songList;
    private int index;
    private MediaPlayer player;
    private Timer timer;
    private MyTask myTask;
    private SharedPreferences sp;//轻量型数据
    private int progress;//存放歌曲上次听到第几毫秒

    public PlayService() {
        Log.d(TAG, "MyService: 构造方法===");
        timer = new Timer();//创建timer
    }

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate: ===");
        sp = getSharedPreferences("saveSongPlayState", MODE_PRIVATE);//轻量型数据
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("TAG", "MyService: onStartCommand======");

        int flag = intent.getIntExtra("flag", 0);
        switch (flag) {
            case FLAG_PLAY:
                boolean flag2 = intent.getIntExtra("pos", 0) == index ? false : true;//true表示播放的是之前的歌曲,接着播就行。false表示播的是新的歌,要重新开始。
                Log.d(TAG, "onStartCommand: flag2===" + flag2);
                index = intent.getIntExtra("pos", 0);
                doStart(index, flag2);
                break;
            case FLAG_PAUSE:
                doPause();
                break;
            case FlAG_PROGRESS:
                int progress = intent.getIntExtra("progress", 0);
                Log.d(TAG, "onStartCommand: service方收到的毫秒值为===" + progress);
                player.seekTo(progress);
                break;
        }
        return super.onStartCommand(intent, flags, startId);
    }

    //播放音乐
    private void doStart(int pos, boolean restart) {
        Log.d(TAG, "doStart: restart===" + restart);
        if (player != null && restart) {//表示要播放另一首歌
            player.stop();
            player.reset();
            player.release();//释放资源
            player = null;

            timer.cancel();
            myTask.cancel();
            myTask = null;
            timer = null;

            progress = 0;//放下一首歌之前,将记录清零
//            player.seekTo(getSongProgress());//将进度重置为上次的
        }
        if (player == null) {//说明是本次打开app播放的第一首歌
            Log.d(TAG, "doStart: songList===" + songList);

            Uri uri = Uri.fromFile(new File(songList.get(pos).getSongPathname()));
//            Log.d(TAG, "doStart: uri===" + uri);
            player = MediaPlayer.create(this, uri);

            player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    timer = new Timer();
                    myTask = new MyTask(timer);
                    timer.schedule(myTask, 0, 500);
                }
            });

//            player.seekTo(getSongProgress());//将进度重置为上次的
        }

        player.start();

        //播放完毕后发广播
        player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Log.d(TAG, "onCompletion: 本首歌播放完毕===");
                Intent intent = new Intent();
                intent.putExtra("curProgress", -99);//-99表示本首歌播放完毕
                intent.setAction("com.hipeak.musicplayerbyservice.music");
                sendBroadcast(intent);
            }
        });


    }

    //暂停播放
    private void doPause() {
        if (player != null) {
            player.pause();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ===");
        Bundle bundle = intent.getExtras();
        songList = (List<Song>) bundle.getSerializable("list");//绑定的时候将songList存起来
        return new Binder();

    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ===");
        return super.onUnbind(intent);
    }

    //service销毁时释放资源
    @Override
    public void onDestroy() {
        Log.d("TAG", "MyService: onDestroy======");
        super.onDestroy();
        if (player != null) {
            player.stop();
            player.reset();
            player.release();//释放资源
            player = null;
        }
    }

//    public class LocalBinder extends Binder {
//        public PlayService getService() {
//            return PlayService.this;
//        }
//
//        public String fun() {
//            return "测试fun()功能";
//        }
//    }

    //定时发广播
    private class MyTask extends TimerTask {
        private Timer timer;

        public MyTask(Timer timer) {
            this.timer = timer;
        }

        @Override
        public void run() {
            //发广播
//            Log.d(TAG, "run: 发广播===");

            Intent intent = new Intent();
            intent.putExtra("curProgress", player.getCurrentPosition());
//            Log.d(TAG, "run: 发送的广播内容为===" + player.getCurrentPosition());
            intent.setAction("com.hipeak.musicplayerbyservice.music");
            sendBroadcast(intent);//发送无序广播

        }
    }

    //拿到上次听到第几毫秒了
    private int getSongProgress() {
        if (sp != null) {
            progress = sp.getInt("progress", 0);
        }
        Log.d(TAG, "get: 读取的值===之前听到哪里了:" + progress);
        return progress;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值