Skip to content

Commit

Permalink
Merge pull request #933 from breez/savage-android-notification-fixes
Browse files Browse the repository at this point in the history
Android notification fixes
  • Loading branch information
dangeross authored Apr 15, 2024
2 parents 12b9ef2 + fb40859 commit 53bf37d
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package breez_sdk_notification

object Constants {
const val SERVICE_TIMEOUT_MS = 3 * 60 * 1000L
const val SHUTDOWN_DELAY_MS = 60 * 1000L

// Notification Channels
const val NOTIFICATION_CHANNEL_FOREGROUND_SERVICE = "FOREGROUND_SERVICE"
const val NOTIFICATION_CHANNEL_LNURL_PAY = "LNURL_PAY"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import breez_sdk_notification.Constants.MESSAGE_TYPE_LNURL_PAY_INFO
import breez_sdk_notification.Constants.MESSAGE_TYPE_LNURL_PAY_INVOICE
import breez_sdk_notification.Constants.MESSAGE_TYPE_PAYMENT_RECEIVED
import breez_sdk_notification.Constants.NOTIFICATION_ID_FOREGROUND_SERVICE
import breez_sdk_notification.Constants.SERVICE_TIMEOUT_MS
import breez_sdk_notification.Constants.SHUTDOWN_DELAY_MS
import breez_sdk_notification.NotificationHelper.Companion.notifyForegroundService
import breez_sdk_notification.job.Job
Expand Down Expand Up @@ -53,6 +54,7 @@ abstract class ForegroundService : SdkForegroundService, EventListener, Service(
return null
}

/** Called by a Job to signal that it is complete. */
override fun onFinished(job: Job) {
synchronized(this) {
logger.log(TAG, "Job has finished: $job", "DEBUG")
Expand All @@ -62,14 +64,27 @@ abstract class ForegroundService : SdkForegroundService, EventListener, Service(
}

/** Stop the service */
private val serviceTimeoutHandler = Handler(Looper.getMainLooper())
private val serviceTimeoutRunnable: Runnable = Runnable {
logger.log(TAG, "Reached service timeout...", "DEBUG")
synchronized(this) {
jobs.forEach { job -> job.onShutdown() }
}

shutdown()
}

private val shutdownHandler = Handler(Looper.getMainLooper())
private val shutdownRunnable: Runnable = Runnable {
logger.log(TAG, "Reached scheduled shutdown...", "DEBUG")
shutdown()
}

private fun resetShutdown() {
private fun resetDelayedCallbacks() {
serviceTimeoutHandler.removeCallbacksAndMessages(null)
shutdownHandler.removeCallbacksAndMessages(null)

shutdownHandler.postDelayed(serviceTimeoutRunnable, SERVICE_TIMEOUT_MS)
}

private fun delayedShutdown() {
Expand All @@ -84,14 +99,10 @@ abstract class ForegroundService : SdkForegroundService, EventListener, Service(
stopSelf()
}

// =========================================================== //
// START COMMAND HANDLER //
// =========================================================== //

/** Called when an intent is called for this service. */
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
resetShutdown()
resetDelayedCallbacks()

val intentDetails = "[ intent=$intent, flag=$flags, startId=$startId ]"
logger.log(TAG, "Start foreground service from intent $intentDetails", "DEBUG")
Expand Down Expand Up @@ -127,7 +138,7 @@ abstract class ForegroundService : SdkForegroundService, EventListener, Service(
abstract fun getConnectRequest(): ConnectRequest?

/** To be implemented by the application foreground service.
* Allows the user to override the default ServiceConfig. */
* Allows the user to override the default ServiceConfig. */
abstract fun getServiceConfig(): ServiceConfig?

/** Get the job to be executed from the Message data in the Intent.
Expand Down Expand Up @@ -189,6 +200,7 @@ abstract class ForegroundService : SdkForegroundService, EventListener, Service(
}
}

/** Handles incoming events from the Breez SDK EventListener */
override fun onEvent(e: BreezEvent) {
synchronized(this) {
jobs.forEach { job -> job.onEvent(e) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.content.Context
import android.util.Log
import breez_sdk_notification.Constants.MESSAGE_TYPE_ADDRESS_TXS_CONFIRMED
import breez_sdk_notification.Constants.MESSAGE_TYPE_PAYMENT_RECEIVED
import breez_sdk_notification.NotificationHelper.Companion.getNotificationManager

@Suppress("unused")
interface MessagingService {
Expand All @@ -22,12 +23,13 @@ interface MessagingService {
/** Check if the foreground service is needed depending on the
* message type and foreground state of the application. */
fun startServiceIfNeeded(context: Context, message: Message) {
val notificationManager = getNotificationManager(context)
val isServiceNeeded = when (message.type) {
MESSAGE_TYPE_ADDRESS_TXS_CONFIRMED -> !isAppForeground(context)
MESSAGE_TYPE_PAYMENT_RECEIVED -> !isAppForeground(context)
else -> true
}
if (isServiceNeeded) startForegroundService(message)
if (notificationManager != null && isServiceNeeded) startForegroundService(message)
else Log.w(TAG, "Ignoring message ${message.type}: ${message.payload}")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class NotificationHelper {
private const val TAG = "NotificationHelper"
private var defaultClickAction: String? = null

private fun getNotificationManager(context: Context): NotificationManager? {
fun getNotificationManager(context: Context): NotificationManager? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE)
Expand All @@ -85,7 +85,7 @@ class NotificationHelper {
}

@SuppressLint("NewApi")
private fun createNotificationChannelGroup(
fun createNotificationChannelGroup(
context: Context,
groupId: String,
groupName: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,13 @@ import breez_sdk.BlockingBreezServices
import breez_sdk.EventListener

interface Job : EventListener {
/** When the notification service is connected to the Breez SDK
* it calls `start` to initiate the job.
*/
fun start(breezSDK: BlockingBreezServices)

/** When the short service timeout is reached it calls `onShutdown`
* to cleanup the job.
*/
fun onShutdown()
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,6 @@ class LnurlPayInfoJob(

fgService.onFinished(this)
}

override fun onShutdown() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,6 @@ class LnurlPayInvoiceJob(

fgService.onFinished(this)
}

override fun onShutdown() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class ReceivePaymentJob(
}
}

override fun onShutdown() {}

private fun handleReceivedPayment(
bolt11: String,
paymentHash: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class RedeemSwapJob(
breezSDK.redeemSwap(request.address)
logger.log(TAG, "Found swap for ${request.address}", "INFO")
} catch (e: Exception) {
logger.log(TAG, "Failed to manually reedeem swap notification: ${e.message}", "WARN")
logger.log(TAG, "Failed to manually redeem swap notification: ${e.message}", "WARN")
}
}

Expand All @@ -47,7 +47,7 @@ class RedeemSwapJob(
when (e) {
is BreezEvent.SwapUpdated -> {
val swapInfo = e.details
logger.log(TAG, "Received swap updated event: ${swapInfo.bitcoinAddress} current address: ${address} status: ${swapInfo.status}", "TRACE")
logger.log(TAG, "Received swap updated event: ${swapInfo.bitcoinAddress} current address: $address status: ${swapInfo.status}", "TRACE")
if (swapInfo.bitcoinAddress == address) {
if (swapInfo.paidMsat.toLong() > 0) {
notifySuccessAndShutdown(address)
Expand All @@ -60,8 +60,10 @@ class RedeemSwapJob(
}
}

override fun onShutdown() {}

private fun notifySuccessAndShutdown(address: String) {
logger.log(TAG, "Swap address ${address} redeemed succesfully", "INFO")
logger.log(TAG, "Swap address $address redeemed successfully", "INFO")
notifyChannel(
context,
NOTIFICATION_CHANNEL_SWAP_TX_CONFIRMED,
Expand Down

0 comments on commit 53bf37d

Please sign in to comment.