|
|
|
@ -5,6 +5,7 @@ import android.app.NotificationChannel |
|
|
|
import android.app.NotificationManager |
|
|
|
import android.content.Context |
|
|
|
import android.content.Intent |
|
|
|
import android.graphics.BitmapFactory |
|
|
|
import android.media.AudioManager |
|
|
|
import android.media.MediaPlayer |
|
|
|
import android.os.Build |
|
|
|
@ -17,6 +18,8 @@ import androidx.core.app.NotificationCompat |
|
|
|
import androidx.media.MediaBrowserServiceCompat |
|
|
|
import androidx.media.session.MediaButtonReceiver |
|
|
|
import com.yunqiinnovation.deepvoice_utils.FileLogger |
|
|
|
import java.net.HttpURLConnection |
|
|
|
import java.net.URL |
|
|
|
import java.util.concurrent.atomic.AtomicBoolean |
|
|
|
|
|
|
|
class MusicService : MediaBrowserServiceCompat() { |
|
|
|
@ -29,7 +32,7 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
private val isRunning = AtomicBoolean(false) |
|
|
|
private var currentUrlInternal: String? = null |
|
|
|
private var currentStatus = false |
|
|
|
private var playlist = mutableListOf<String>() |
|
|
|
private var playlist = mutableListOf<Map<String,String>>() |
|
|
|
private var currentIndex = 0 |
|
|
|
|
|
|
|
fun isServiceRunning() = isRunning.get() |
|
|
|
@ -46,7 +49,7 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
FileLogger.init(this) |
|
|
|
isRunning.set(true) |
|
|
|
setupMediaSession() |
|
|
|
startForeground(NOTIFICATION_ID, createNotification("等待播放…")) |
|
|
|
startForeground(NOTIFICATION_ID, createNotification("等待播放","DeepSound","")) |
|
|
|
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager |
|
|
|
FileLogger.i(TAG, "MediaService 启动完成") |
|
|
|
} |
|
|
|
@ -59,12 +62,34 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
} |
|
|
|
|
|
|
|
val command = intent?.getStringExtra("command") ?: return START_NOT_STICKY |
|
|
|
FileLogger.i(TAG, "收到命令: $command") |
|
|
|
FileLogger.i(TAG, "liwei------------------- onStartCommand: $command") |
|
|
|
when (command) { |
|
|
|
"play" -> intent.getStringExtra("url")?.let { url -> |
|
|
|
if (!playlist.contains(url)) playlist.add(url) |
|
|
|
currentIndex = playlist.indexOf(url) |
|
|
|
play(url) |
|
|
|
"play" -> intent.getSerializableExtra("song")?.let { url -> |
|
|
|
val songMap = intent.getSerializableExtra("song") as? Map<String, String> |
|
|
|
songMap?.let { song -> |
|
|
|
val songId = song["id"] ?: return@let |
|
|
|
|
|
|
|
val existingIndex = playlist.indexOfFirst { it["id"] == songId } |
|
|
|
if (existingIndex == -1) { |
|
|
|
playlist.add(song) |
|
|
|
currentIndex = playlist.size - 1 |
|
|
|
} else { |
|
|
|
currentIndex = existingIndex |
|
|
|
} |
|
|
|
|
|
|
|
play(song) |
|
|
|
} |
|
|
|
} |
|
|
|
"playlist" -> { |
|
|
|
|
|
|
|
@Suppress("UNCHECKED_CAST") |
|
|
|
val list = intent.getSerializableExtra("songs") as? ArrayList<HashMap<String, String>> |
|
|
|
list?.let { |
|
|
|
playlist.clear() |
|
|
|
playlist.addAll(it) |
|
|
|
currentIndex = 0 |
|
|
|
play(playlist[currentIndex]) |
|
|
|
} |
|
|
|
} |
|
|
|
"pause" -> pause() |
|
|
|
"resume" -> resume() |
|
|
|
@ -106,7 +131,7 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
setSessionToken(mediaSession.sessionToken) |
|
|
|
} |
|
|
|
|
|
|
|
private fun createNotification(contentText: String): Notification { |
|
|
|
private fun createNotification(title: String,artist: String,coverUrl: String?): Notification { |
|
|
|
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager |
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
|
|
|
manager.createNotificationChannel( |
|
|
|
@ -124,9 +149,9 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
this, PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
|
|
|
) |
|
|
|
|
|
|
|
return NotificationCompat.Builder(this, CHANNEL_ID) |
|
|
|
.setContentTitle("DeepSound") |
|
|
|
.setContentText(contentText) |
|
|
|
val builder = NotificationCompat.Builder(this, CHANNEL_ID) |
|
|
|
.setContentTitle(title) |
|
|
|
.setContentText(artist) |
|
|
|
.setSmallIcon(android.R.drawable.ic_media_play) |
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) |
|
|
|
.setStyle( |
|
|
|
@ -142,7 +167,31 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
) |
|
|
|
.addAction(android.R.drawable.ic_media_next, "下一首", nextIntent) |
|
|
|
.setOngoing(currentStatus) |
|
|
|
.build() |
|
|
|
|
|
|
|
// 异步加载封面图 |
|
|
|
if (!coverUrl.isNullOrEmpty()) { |
|
|
|
Thread { |
|
|
|
try { |
|
|
|
val url = URL(coverUrl) |
|
|
|
val connection = url.openConnection() as HttpURLConnection |
|
|
|
connection.doInput = true |
|
|
|
connection.connect() |
|
|
|
val inputStream = connection.inputStream |
|
|
|
val bitmap = BitmapFactory.decodeStream(inputStream) |
|
|
|
|
|
|
|
// 设置大图标并更新通知 |
|
|
|
builder.setLargeIcon(bitmap) |
|
|
|
val builtNotification = builder.build() |
|
|
|
manager.notify(NOTIFICATION_ID, builtNotification) |
|
|
|
} catch (e: Exception) { |
|
|
|
e.printStackTrace() |
|
|
|
manager.notify(NOTIFICATION_ID, builder.build()) |
|
|
|
} |
|
|
|
}.start() |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return builder.build() |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -171,7 +220,12 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private fun play(url: String) { |
|
|
|
private fun play(song: Map<String,String>) { |
|
|
|
val url = song["url"] ?: return |
|
|
|
FileLogger.i(TAG, "开始播放: $url") |
|
|
|
val title = song["title"] ?: "未知标题" |
|
|
|
val artist = song["artist"] ?: "未知歌手" |
|
|
|
val coverUrl = song["coverUrl"] |
|
|
|
mediaPlayer?.release() |
|
|
|
currentStatus = true |
|
|
|
currentUrlInternal = url |
|
|
|
@ -180,7 +234,7 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
setAudioStreamType(AudioManager.STREAM_MUSIC) |
|
|
|
setOnPreparedListener { |
|
|
|
start() |
|
|
|
updateNotification("正在播放") |
|
|
|
updateNotification(title,artist,coverUrl) |
|
|
|
FileLogger.i(TAG, "开始播放: $url") |
|
|
|
} |
|
|
|
setOnCompletionListener { playNextOrStop() } |
|
|
|
@ -202,7 +256,11 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
.setState(PlaybackStateCompat.STATE_PAUSED, currentPosition.toLong(), 1.0f) |
|
|
|
.build() |
|
|
|
) |
|
|
|
updateNotification("已暂停") |
|
|
|
val song = playlist[currentIndex] |
|
|
|
val title = song["title"] ?: "未知标题" |
|
|
|
val artist = song["artist"] ?: "未知歌手" |
|
|
|
val coverUrl = song["coverUrl"] |
|
|
|
updateNotification(title,artist,coverUrl) |
|
|
|
setPlaybackState(PlaybackStateCompat.STATE_PLAYING); |
|
|
|
FileLogger.i(TAG, "已暂停") |
|
|
|
|
|
|
|
@ -218,9 +276,13 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
.setState(PlaybackStateCompat.STATE_PLAYING, currentPosition.toLong(), 1.0f) |
|
|
|
.build() |
|
|
|
) |
|
|
|
updateNotification("继续播放") |
|
|
|
val song = playlist[currentIndex] |
|
|
|
val title = song["title"] ?: "未知标题" |
|
|
|
val artist = song["artist"] ?: "未知歌手" |
|
|
|
val coverUrl = song["coverUrl"] |
|
|
|
updateNotification(title,artist,coverUrl) |
|
|
|
setPlaybackState(PlaybackStateCompat.STATE_PAUSED); |
|
|
|
FileLogger.i(TAG, "继续播放") |
|
|
|
// FileLogger.i(TAG, "继续播放") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -240,8 +302,8 @@ class MusicService : MediaBrowserServiceCompat() { |
|
|
|
else stopSelf() |
|
|
|
} |
|
|
|
|
|
|
|
private fun updateNotification(contentText: String) { |
|
|
|
val notification = createNotification(contentText) |
|
|
|
private fun updateNotification(title: String,artist: String,coverUrl: String?) { |
|
|
|
val notification = createNotification(title, artist, coverUrl) |
|
|
|
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager |
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { |
|
|
|
manager.notify(NOTIFICATION_ID, notification) |
|
|
|
|