Skip to content

Commit

Permalink
Avoid crashing if service can't start up while in background
Browse files Browse the repository at this point in the history
Sort of addresses #94
  • Loading branch information
arkon committed Jun 6, 2024
1 parent 67e1af3 commit 9a184be
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 27 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ target/
# Java class files
*.class

# Kotlin compiler
.kotlin/

# Local configuration file (sdk path, etc)
local.properties
.gitattributes
Expand Down
31 changes: 14 additions & 17 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
alias(libs.plugins.android.application)
id("com.mikepenz.aboutlibraries.plugin")
Expand Down Expand Up @@ -160,21 +158,20 @@ ktlint {
}
}

tasks {
withType<KotlinCompile> {
kotlin {
compilerOptions {
// See https://kotlinlang.org/docs/reference/experimental.html#experimental-status-of-experimental-api-markers
compilerOptions {
freeCompilerArgs.addAll(
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
"-opt-in=kotlin.Experimental",
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-opt-in=kotlinx.coroutines.FlowPreview",
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=2.0.0-RC1",
)
}
freeCompilerArgs.addAll(
"-Xcontext-receivers",
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
"-opt-in=kotlin.Experimental",
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-opt-in=kotlinx.coroutines.FlowPreview",
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=2.0.0-RC1",
)
}
}
39 changes: 29 additions & 10 deletions app/src/main/kotlin/me/echeung/moemoekyun/service/MusicNotifier.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
package me.echeung.moemoekyun.service

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.content.pm.ServiceInfo
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import logcat.LogPriority
import logcat.logcat
import me.echeung.moemoekyun.R
import me.echeung.moemoekyun.client.api.Stream
import me.echeung.moemoekyun.domain.songs.model.DomainSong
import me.echeung.moemoekyun.ui.MainActivity
import me.echeung.moemoekyun.util.AlbumArtUtil
import me.echeung.moemoekyun.util.ext.notifyIfPermitted
import javax.inject.Inject

class MusicNotifier @Inject constructor(
private val albumArtUtil: AlbumArtUtil,
) {

@SuppressLint("MissingPermission")
fun update(service: AppService, currentSong: DomainSong?, streamState: Stream.State, isAuthenticated: Boolean) {
if (currentSong == null || service.mediaSession == null || streamState == Stream.State.STOPPED) {
return
Expand Down Expand Up @@ -85,15 +88,31 @@ class MusicNotifier @Inject constructor(
builder.setStyle(style.setShowActionsInCompactView(0, 1))
}

val notification = builder.build()

if (isPlaying) {
service.startForeground(NOTIFICATION_ID, notification)
} else {
service.stopForeground(Service.STOP_FOREGROUND_DETACH)
// ForegroundServiceStartNotAllowedException can be thrown in Android 12+
// if this ends up getting started once the app was already backgrounded.
try {
val notification = builder.build()

if (isPlaying) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
service.startForeground(
NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
)
} else {
service.startForeground(NOTIFICATION_ID, notification)
}
} else {
service.stopForeground(Service.STOP_FOREGROUND_DETACH)
}

with(service) {
NotificationManagerCompat.from(service).notifyIfPermitted(NOTIFICATION_ID, notification)
}
} catch (e: IllegalStateException) {
logcat(LogPriority.ERROR) { "Failed to start foreground service" }
}

NotificationManagerCompat.from(service).notify(NOTIFICATION_ID, notification)
}

private fun getPlaybackActionService(service: AppService, intentAction: String): PendingIntent {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package me.echeung.moemoekyun.util.ext

import android.Manifest
import android.app.Notification
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationManagerCompat

context(Context)
fun NotificationManagerCompat.notifyIfPermitted(id: Int, notification: Notification) {
if (ActivityCompat.checkSelfPermission(
this@Context,
Manifest.permission.POST_NOTIFICATIONS,
) == PackageManager.PERMISSION_GRANTED
) {
notify(id, notification)
}
}

0 comments on commit 9a184be

Please sign in to comment.