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;
}
}