Skip to content

Commit 2043eef

Browse files
committed
feat: enhance artist page functionality and UI, fix various issues
1 parent e85bdaa commit 2043eef

7 files changed

Lines changed: 129 additions & 61 deletions

File tree

.github/workflows/android.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build release APK (Full)
1+
name: Build release APK (FOSS)
22
on:
33
workflow_dispatch:
44
push:
@@ -45,7 +45,7 @@ jobs:
4545
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> ./local.properties
4646
4747
- name: Build release APK
48-
run: ./gradlew app:assembleFullRelease
48+
run: ./gradlew app:assembleFossRelease
4949

5050
- name: Check build-tools version
5151
shell: bash
@@ -57,7 +57,7 @@ jobs:
5757
- uses: kevin-david/zipalign-sign-android-release@v2
5858
id: sign_app
5959
with:
60-
releaseDirectory: app/build/outputs/apk/full/release
60+
releaseDirectory: app/build/outputs/apk/foss/release
6161
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
6262
alias: ${{ secrets.ALIAS }}
6363
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
@@ -70,4 +70,4 @@ jobs:
7070
uses: actions/upload-artifact@v4
7171
with:
7272
name: app
73-
path: app/build/outputs/apk/full/release/*-signed.apk
73+
path: app/build/outputs/apk/foss/release/*-signed.apk

app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.content.Intent
77
import android.os.Binder
88
import android.os.IBinder
99
import android.util.Log
10+
import androidx.media3.common.Player
1011
import androidx.media3.common.util.UnstableApi
1112
import androidx.media3.exoplayer.ExoPlayer
1213
import androidx.media3.session.DefaultMediaNotificationProvider
@@ -41,6 +42,22 @@ class SimpleMediaService :
4142

4243
private val binder = MusicBinder()
4344

45+
inner class MusicBinder : Binder()
46+
47+
override fun onBind(intent: Intent?): IBinder {
48+
super.onBind(intent)
49+
Log.w("Service", "Simple Media Service Bound")
50+
return binder
51+
}
52+
53+
override fun onUnbind(intent: Intent?): Boolean {
54+
if (simpleMediaServiceHandler.shouldReleaseOnTaskRemoved()) {
55+
release()
56+
}
57+
Log.w("Service", "Simple Media Service Unbound")
58+
return super.onUnbind(intent)
59+
}
60+
4461
@UnstableApi
4562
override fun onCreate() {
4663
super.onCreate()
@@ -111,15 +128,28 @@ class SimpleMediaService :
111128
}
112129

113130
@UnstableApi
114-
private fun release() {
131+
fun release() {
132+
Log.w("Service", "Starting release process")
115133
runBlocking {
116-
simpleMediaServiceHandler.release()
117-
mediaSession?.run {
118-
player.stop()
119-
this.release()
120-
player.release()
134+
try {
135+
// Release handler first (contains coroutines and jobs)
136+
simpleMediaServiceHandler.release()
137+
138+
// Release MediaSession and Player
139+
mediaSession?.run {
140+
this.release()
141+
if (this.player.playbackState != Player.STATE_IDLE) {
142+
this.player.seekTo(0)
143+
this.player.playWhenReady = false
144+
this.player.stop()
145+
}
146+
}
121147
mediaSession = null
148+
Log.w("Service", "Simple Media Service Released")
149+
} catch (e: Exception) {
150+
Log.e("Service", "Error during release", e)
122151
}
152+
stopSelf()
123153
}
124154
}
125155

@@ -130,25 +160,19 @@ class SimpleMediaService :
130160
}
131161

132162
override fun onTrimMemory(level: Int) {
133-
super.onTrimMemory(level)
163+
Log.w("Service", "Simple Media Service Trim Memory Level: $level")
134164
simpleMediaServiceHandler.mayBeSaveRecentSong()
135165
}
136166

137167
@UnstableApi
138168
override fun onTaskRemoved(rootIntent: Intent?) {
169+
Log.w("Service", "Simple Media Service Task Removed")
139170
if (simpleMediaServiceHandler.shouldReleaseOnTaskRemoved()) {
140171
release()
172+
super.onTaskRemoved(rootIntent)
141173
}
142-
super.onTaskRemoved(rootIntent)
143174
}
144175

145-
inner class MusicBinder : Binder() {
146-
val service: SimpleMediaService
147-
get() = this@SimpleMediaService
148-
}
149-
150-
override fun onBind(intent: Intent?): IBinder = super.onBind(intent) ?: binder
151-
152176
// Can't inject by Koin because it depend on service
153177
@UnstableApi
154178
private fun provideMediaLibrarySession(

app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaServiceHandler.kt

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ class SimpleMediaServiceHandler(
106106
private var secondLoudnessEnhancer: LoudnessEnhancer? = null
107107

108108
private var volumeNormalizationJob: Job? = null
109-
private var volumeNormalizationForSecondPlayerJob: Job? = null
110109

111110
private var sleepTimerJob: Job? = null
112111

@@ -1524,28 +1523,71 @@ class SimpleMediaServiceHandler(
15241523
}
15251524

15261525
fun release() {
1527-
mayBeSaveRecentSong(true)
1528-
mayBeSavePlaybackState()
1529-
player.stop()
1530-
player.playWhenReady = false
1531-
player.removeListener(this)
1532-
sendCloseEqualizerIntent()
1533-
progressJob?.cancel()
1534-
progressJob = null
1535-
bufferedJob?.cancel()
1536-
bufferedJob = null
1537-
sleepTimerJob?.cancel()
1538-
sleepTimerJob = null
1539-
volumeNormalizationJob?.cancel()
1540-
volumeNormalizationJob = null
1541-
toggleLikeJob?.cancel()
1542-
toggleLikeJob = null
1543-
updateNotificationJob?.cancel()
1544-
updateNotificationJob = null
1545-
loadJob?.cancel()
1546-
loadJob = null
1547-
coroutineScope.cancel()
1548-
Log.w("Service", "scope is active: ${coroutineScope.isActive}")
1526+
Log.w("ServiceHandler", "Starting release process")
1527+
try {
1528+
// Save state first
1529+
mayBeSaveRecentSong(true)
1530+
mayBeSavePlaybackState()
1531+
1532+
// Stop and release player
1533+
player.stop()
1534+
player.playWhenReady = false
1535+
player.removeListener(this)
1536+
1537+
// Release audio effects
1538+
try {
1539+
loudnessEnhancer?.enabled = false
1540+
loudnessEnhancer?.release()
1541+
loudnessEnhancer = null
1542+
1543+
secondLoudnessEnhancer?.enabled = false
1544+
secondLoudnessEnhancer?.release()
1545+
secondLoudnessEnhancer = null
1546+
} catch (e: Exception) {
1547+
Log.e("ServiceHandler", "Error releasing audio effects", e)
1548+
}
1549+
1550+
// Send close equalizer intent
1551+
sendCloseEqualizerIntent()
1552+
1553+
// Cancel all jobs
1554+
progressJob?.cancel()
1555+
progressJob = null
1556+
bufferedJob?.cancel()
1557+
bufferedJob = null
1558+
sleepTimerJob?.cancel()
1559+
sleepTimerJob = null
1560+
volumeNormalizationJob?.cancel()
1561+
volumeNormalizationJob = null
1562+
toggleLikeJob?.cancel()
1563+
toggleLikeJob = null
1564+
updateNotificationJob?.cancel()
1565+
updateNotificationJob = null
1566+
loadJob?.cancel()
1567+
loadJob = null
1568+
songEntityJob?.cancel()
1569+
songEntityJob = null
1570+
downloadImageForWidgetJob?.cancel()
1571+
downloadImageForWidgetJob = null
1572+
getSkipSegmentsJob?.cancel()
1573+
getSkipSegmentsJob = null
1574+
getFormatJob?.cancel()
1575+
getFormatJob = null
1576+
jobWatchtime?.cancel()
1577+
jobWatchtime = null
1578+
getDataOfNowPlayingTrackStateJob?.cancel()
1579+
getDataOfNowPlayingTrackStateJob = null
1580+
1581+
// Cancel coroutine scope
1582+
coroutineScope.cancel()
1583+
1584+
// Clear callbacks
1585+
setNotificationLayout = null
1586+
1587+
Log.w("ServiceHandler", "Handler released successfully. Scope active: ${coroutineScope.isActive}")
1588+
} catch (e: Exception) {
1589+
Log.e("ServiceHandler", "Error during release", e)
1590+
}
15491591
}
15501592

15511593
@SuppressLint("PrivateResource")

app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ import java.util.Locale
8686
class MainActivity : AppCompatActivity() {
8787
val viewModel: SharedViewModel by inject()
8888

89+
private var mBound = false
90+
private var shouldUnbind = false
8991
private val serviceConnection =
9092
object : ServiceConnection {
9193
override fun onServiceConnected(
@@ -94,11 +96,13 @@ class MainActivity : AppCompatActivity() {
9496
) {
9597
if (service is SimpleMediaService.MusicBinder) {
9698
Log.w("MainActivity", "onServiceConnected: ")
99+
mBound = true
97100
}
98101
}
99102

100103
override fun onServiceDisconnected(name: ComponentName?) {
101104
Log.w("MainActivity", "onServiceDisconnected: ")
105+
mBound = false
102106
}
103107
}
104108

@@ -117,11 +121,6 @@ class MainActivity : AppCompatActivity() {
117121
// EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
118122
// }
119123

120-
override fun onResume() {
121-
super.onResume()
122-
Log.d("MainActivity", "onResume: ")
123-
}
124-
125124
@UnstableApi
126125
@ExperimentalMaterial3Api
127126
@ExperimentalFoundationApi
@@ -548,10 +547,13 @@ class MainActivity : AppCompatActivity() {
548547
}
549548

550549
override fun onDestroy() {
551-
Log.w("MainActivity", "onDestroy: ")
552-
if (viewModel.shouldStopMusicService()) {
553-
viewModel.isServiceRunning = false
550+
val shouldStopMusicService = viewModel.shouldStopMusicService()
551+
Log.w("MainActivity", "onDestroy: Should stop service $shouldStopMusicService")
552+
553+
// Always unbind service if it was bound to prevent MusicBinder leak
554+
if (shouldStopMusicService && shouldUnbind) {
554555
unbindService(serviceConnection)
556+
viewModel.isServiceRunning = false
555557
}
556558
unloadKoinModules(viewModelModule)
557559
super.onDestroy()
@@ -563,14 +565,12 @@ class MainActivity : AppCompatActivity() {
563565
}
564566

565567
private fun startMusicService() {
566-
println("go to StartMusicService")
567-
if (!viewModel.recreateActivity.value) {
568-
val intent = Intent(this, SimpleMediaService::class.java)
569-
startService(intent)
570-
bindService(intent, serviceConnection, BIND_AUTO_CREATE)
571-
viewModel.isServiceRunning = true
572-
Log.d("Service", "Service started")
573-
}
568+
val intent = Intent(this, SimpleMediaService::class.java)
569+
startService(intent)
570+
bindService(intent, serviceConnection, BIND_AUTO_CREATE)
571+
viewModel.isServiceRunning = true
572+
shouldUnbind = true
573+
Log.d("Service", "Service started")
574574
}
575575

576576
private fun checkForUpdate() {

fastlane/metadata/android/en-US/changelogs/38.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
- Fixed Spotify
33
- Fixed Android Auto problems
44
- Fixed video being stretched to 16:9
5+
- Fixed "Killed service" error
56
- PIP support in Fullscreen
67
- Subtitle inside every video
78
- Option to backup downloaded songs

fastlane/metadata/android/vi-VN/changelogs/38.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
- Sửa lỗi Spotify
33
- Sửa lỗi Android Auto
44
- Sửa lỗi video bị kéo dãn thành tỷ lệ 16:9
5+
- Sửa lỗi "Dịch vụ bị giết"
56
- Hỗ trợ PIP khi ở chế độ toàn màn hình
67
- Phụ đề trong mọi video
78
- Tùy chọn sao lưu các bài hát đã tải xuống

gradle/libs.versions.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ sdp-android = "1.1.1"
4949
ssp-android = "1.1.1"
5050
aboutlibraries = "12.2.4"
5151
flexbox = "3.0.0"
52-
balloon = "1.6.12"
52+
balloon = "1.6.13"
5353
insetsx = "0.1.0-alpha10"
5454
ktor = "3.2.3"
5555
brotli = "0.1.2"
@@ -67,9 +67,9 @@ json = "1.9.0"
6767
gemini-kotlin = "4.0.2"
6868
slf4j = "1.7.36"
6969
sentry-android = "8.18.0"
70-
sentry-gradle = "5.8.0"
70+
sentry-gradle = "5.8.1"
7171
newpipe = "7adbc48a0aa872c016b8ec089e278d5e12772054"
72-
leakcanary = "2.14"
72+
leakcanary = "3.0-alpha-8"
7373

7474
[libraries]
7575
desugaring = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugaring"}

0 commit comments

Comments
 (0)