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
2 changes: 1 addition & 1 deletion OneSignalSDK/detekt/detekt-baseline-notifications.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
<ID>LongParameterList:INotificationGenerationWorkManager.kt$INotificationGenerationWorkManager$( context: Context, osNotificationId: String, androidNotificationId: Int, jsonPayload: JSONObject?, timestamp: Long, isRestoring: Boolean, isHighPriority: Boolean, )</ID>
<ID>LongParameterList:INotificationRepository.kt$INotificationRepository$( id: String, groupId: String?, collapseKey: String?, shouldDismissIdenticals: Boolean, isOpened: Boolean, androidId: Int, title: String?, body: String?, expireTime: Long, jsonPayload: String, )</ID>
<ID>LongParameterList:NotificationLifecycleService.kt$NotificationLifecycleService$( private val _applicationService: IApplicationService, private val _time: ITime, private val _configModelStore: ConfigModelStore, private val _influenceManager: IInfluenceManager, private val _subscriptionManager: ISubscriptionManager, private val _deviceService: IDeviceService, private val _backend: INotificationBackendService, private val _receiveReceiptWorkManager: IReceiveReceiptWorkManager, private val _analyticsTracker: IAnalyticsTracker, )</ID>
<ID>LoopWithTooManyJumpStatements:NotificationLifecycleService.kt$NotificationLifecycleService$for (i in 0 until data.length()) { val notificationId = NotificationFormatHelper.getOSNotificationIdFromJson(data[i] as JSONObject?) ?: continue if (postedOpenedNotifIds.contains(notificationId)) { continue } postedOpenedNotifIds.add(notificationId) suspendifyWithErrorHandling( useIO = true, // or false for CPU operations block = { _backend.updateNotificationAsOpened( appId, notificationId, subscriptionId, deviceType, ) }, onError = { ex -> if (ex is BackendException) { Logging.error("Notification opened confirmation failed with statusCode: ${ex.statusCode} response: ${ex.response}") } else { Logging.error("Unexpected error in notification opened confirmation", ex) } }, ) }</ID>
<ID>LoopWithTooManyJumpStatements:NotificationLifecycleService.kt$NotificationLifecycleService$for (i in 0 until data.length()) { val notificationId = NotificationFormatHelper.getOSNotificationIdFromJson(data[i] as JSONObject?) ?: continue if (postedOpenedNotifIds.contains(notificationId)) { continue } postedOpenedNotifIds.add(notificationId) suspendifyWithErrorHandling( useIO = true, // or false for CPU operations block = { confirmNotificationOpened(appId, notificationId, subscriptionId, deviceType) }, onError = { ex -> if (ex is BackendException) { Logging.info("Notification opened confirmation failed with statusCode: ${ex.statusCode} response: ${ex.response}") } else { Logging.info("Unexpected error in notification opened confirmation", ex) } }, ) }</ID>
<ID>MagicNumber:FirebaseAnalyticsTracker.kt$FirebaseAnalyticsTracker$1000</ID>
<ID>MagicNumber:FirebaseAnalyticsTracker.kt$FirebaseAnalyticsTracker$30</ID>
<ID>MagicNumber:FirebaseAnalyticsTracker.kt$FirebaseAnalyticsTracker$60</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.ActivityNotFoundException
import android.content.Context
import com.onesignal.common.AndroidUtils
import com.onesignal.common.JSONUtils
import com.onesignal.common.NetworkUtils
import com.onesignal.common.events.CallbackProducer
import com.onesignal.common.events.EventProducer
import com.onesignal.common.exceptions.BackendException
Expand Down Expand Up @@ -35,6 +36,7 @@ import com.onesignal.notifications.internal.receivereceipt.IReceiveReceiptWorkMa
import com.onesignal.session.internal.influence.IInfluenceManager
import com.onesignal.user.internal.subscriptions.ISubscriptionManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import org.json.JSONArray
import org.json.JSONException
Expand Down Expand Up @@ -146,12 +148,7 @@ internal class NotificationLifecycleService(
useIO = true,
// or false for CPU operations
block = {
_backend.updateNotificationAsOpened(
appId,
notificationId,
subscriptionId,
deviceType,
)
confirmNotificationOpened(appId, notificationId, subscriptionId, deviceType)
},
onError = { ex ->
if (ex is BackendException) {
Expand Down Expand Up @@ -200,6 +197,35 @@ internal class NotificationLifecycleService(
extWillShowInForegroundCallback.fire { it.onWillDisplay(willDisplayEvent) }
}

private suspend fun confirmNotificationOpened(
appId: String,
notificationId: String,
subscriptionId: String,
deviceType: IDeviceService.DeviceType,
) {
for (attempt in 1..NetworkUtils.maxNetworkRequestAttemptCount) {
try {
_backend.updateNotificationAsOpened(appId, notificationId, subscriptionId, deviceType)
return
} catch (ex: BackendException) {
val responseType = NetworkUtils.getResponseStatusType(ex.statusCode)
if (responseType != NetworkUtils.ResponseStatusType.RETRYABLE || attempt >= NetworkUtils.maxNetworkRequestAttemptCount) {
throw ex
}
val retryAfterMs = ex.retryAfterSeconds?.let { it * MILLIS_PER_SECOND } ?: 0L
Comment thread
nan-li marked this conversation as resolved.
val backoffMs = (attempt * RETRY_BACKOFF_MS).toLong()
val delayMs = maxOf(retryAfterMs, backoffMs)
Logging.info("Notification opened confirmation attempt $attempt failed (statusCode: ${ex.statusCode}), retrying in ${delayMs}ms")
delay(delayMs)
}
}
}

companion object {
private const val MILLIS_PER_SECOND = 1_000L
private const val RETRY_BACKOFF_MS = 15_000
}

/**
* In addition to using the setters to set all of the handlers you can also create your own implementation
* within a separate class and give your AndroidManifest.xml a special meta data tag
Expand Down
Loading