Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 51 additions & 17 deletions app/src/main/java/to/bitkit/androidServices/LightningNodeService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import android.app.Notification
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.content.pm.ServiceInfo
import android.os.Build
import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.ServiceCompat
import androidx.core.content.ContextCompat
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineDispatcher
Expand Down Expand Up @@ -59,13 +61,16 @@ class LightningNodeService : Service() {
@Inject
lateinit var cacheStore: CacheStore

private var hasStartedNode = false

override fun onCreate() {
super.onCreate()
startForeground(ID_NOTIFICATION_NODE, createNotification())
setupService()
}

private fun setupService() {
if (hasStartedNode) return
hasStartedNode = true

serviceScope.launch {
lightningRepo.start(
eventHandler = { event ->
Expand Down Expand Up @@ -149,19 +154,49 @@ class LightningNodeService : Service() {
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Logger.debug("onStartCommand", context = TAG)
when (intent?.action) {
val action = intent?.action
Logger.debug("Received start command action '$action'", context = TAG)
when (action) {
ACTION_START_SERVICE -> {
if (promoteToForeground(startId)) setupService()
}
ACTION_STOP_SERVICE_AND_APP -> {
Logger.debug("ACTION_STOP_SERVICE_AND_APP detected", context = TAG)
serviceScope.launch {
lightningRepo.stop()
activityManager.appTasks.forEach { it.finishAndRemoveTask() }
stopSelf()
}
return START_NOT_STICKY
Logger.debug("Received stop service action", context = TAG)
stopForegroundService(startId)
activityManager.appTasks.forEach { it.finishAndRemoveTask() }
serviceScope.launch { lightningRepo.stop() }
}
else -> {
Logger.warn("Stopped service for unsupported action '$action'", context = TAG)
stopSelf(startId)
}
}
return START_STICKY
return START_NOT_STICKY
}

private fun promoteToForeground(startId: Int): Boolean {
return runCatching {
ServiceCompat.startForeground(
this,
ID_NOTIFICATION_NODE,
createNotification(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC,
)
}.fold(
onSuccess = { true },
onFailure = {
if (it !is RuntimeException) throw it

Logger.error("Failed to promote foreground service", it, context = TAG)
stopSelf(startId)
false
}
)
}

private fun stopForegroundService(startId: Int) {
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
stopSelf(startId)
}

override fun onDestroy() {
Expand All @@ -173,11 +208,9 @@ class LightningNodeService : Service() {

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
override fun onTimeout(startId: Int, fgsType: Int) {
Logger.warn("Foreground service timeout reached", context = TAG)
serviceScope.launch {
lightningRepo.stop()
stopSelf()
}
Logger.warn("Reached foreground service timeout for type '$fgsType'", context = TAG)
stopForegroundService(startId)
serviceScope.launch { lightningRepo.stop() }
super.onTimeout(startId, fgsType)
}

Expand All @@ -186,6 +219,7 @@ class LightningNodeService : Service() {
companion object {
const val CHANNEL_ID_NODE = "bitkit_notification_channel_node"
const val TAG = "LightningNodeService"
const val ACTION_START_SERVICE = "to.bitkit.androidServices.action.START_SERVICE"
const val ACTION_STOP_SERVICE_AND_APP = "to.bitkit.androidServices.action.STOP_SERVICE_AND_APP"
}
}
7 changes: 6 additions & 1 deletion app/src/main/java/to/bitkit/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import to.bitkit.R
import to.bitkit.androidServices.LightningNodeService
import to.bitkit.androidServices.LightningNodeService.Companion.ACTION_START_SERVICE
import to.bitkit.androidServices.LightningNodeService.Companion.CHANNEL_ID_NODE
import to.bitkit.models.NewTransactionSheetDetails
import to.bitkit.models.SamRockSetupRequest
Expand Down Expand Up @@ -231,7 +232,11 @@ class MainActivity : FragmentActivity() {
private fun tryStartForegroundService() {
runCatching {
Logger.debug("Attempting to start LightningNodeService", context = "MainActivity")
startForegroundService(Intent(this, LightningNodeService::class.java))
startForegroundService(
Intent(this, LightningNodeService::class.java).apply {
action = ACTION_START_SERVICE
},
)
}.onFailure { error ->
Logger.error("Failed to start LightningNodeService", error, context = "MainActivity")
}
Expand Down
Loading
Loading