diff --git a/CHANGELOG.md b/CHANGELOG.md index f7660a1a..736423b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 3.10.0 + +- Add support for the URLResolver notification type +- Fix anonymous device registration + ## 3.9.1 - Preload in-app message's images diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a922b148..cb5b5381 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] maven-artifactGroup = "re.notifica" -maven-artifactVersion = "3.9.1" +maven-artifactVersion = "3.10.0" android-compileSdk = "34" android-buildTools = "34.0.0" android-minSdk = "23" diff --git a/notificare-push-ui/src/main/java/re/notifica/push/ui/internal/NotificarePushUIImpl.kt b/notificare-push-ui/src/main/java/re/notifica/push/ui/internal/NotificarePushUIImpl.kt index 7d44c53d..abeec103 100644 --- a/notificare-push-ui/src/main/java/re/notifica/push/ui/internal/NotificarePushUIImpl.kt +++ b/notificare-push-ui/src/main/java/re/notifica/push/ui/internal/NotificarePushUIImpl.kt @@ -21,6 +21,7 @@ import re.notifica.push.ui.actions.* import re.notifica.push.ui.actions.base.NotificationAction import re.notifica.push.ui.ktx.loyaltyIntegration import re.notifica.push.ui.notifications.fragments.* +import re.notifica.push.ui.utils.removeQueryParameter @Keep internal object NotificarePushUIImpl : NotificareModule(), NotificarePushUI, NotificareInternalPushUI { @@ -73,6 +74,9 @@ internal object NotificarePushUIImpl : NotificareModule(), NotificarePushUI, Not handleUrlScheme(activity, notification) } + NotificareNotification.NotificationType.URL_RESOLVER -> { + handleUrlResolver(activity, notification) + } NotificareNotification.NotificationType.PASSBOOK -> { onMainThread { lifecycleListeners.forEach { it.onNotificationWillPresent(notification) } @@ -168,6 +172,7 @@ internal object NotificarePushUIImpl : NotificareModule(), NotificarePushUI, Not } NotificareNotification.NotificationType.WEB_VIEW -> NotificareWebViewFragment::class.java.canonicalName NotificareNotification.NotificationType.URL -> NotificareUrlFragment::class.java.canonicalName + NotificareNotification.NotificationType.URL_RESOLVER -> NotificareUrlFragment::class.java.canonicalName NotificareNotification.NotificationType.URL_SCHEME -> { NotificareLogger.debug("Attempting to create a fragment for a notification of type 'UrlScheme'. This type contains no visual interface.") return null @@ -239,6 +244,43 @@ internal object NotificarePushUIImpl : NotificareModule(), NotificarePushUI, Not } } + private fun handleUrlResolver(activity: Activity, notification: NotificareNotification) { + val result = NotificationUrlResolver.resolve(notification) + + when(result) { + NotificationUrlResolver.UrlResolverResult.NONE -> { + NotificareLogger.debug("Resolving as 'none' notification.") + } + NotificationUrlResolver.UrlResolverResult.URL_SCHEME -> { + NotificareLogger.debug("Resolving as 'url scheme' notification.") + + onMainThread { + lifecycleListeners.forEach { it.onNotificationWillPresent(notification) } + } + + handleUrlScheme(activity, notification) + } + NotificationUrlResolver.UrlResolverResult.WEB_VIEW -> { + NotificareLogger.debug("Resolving as 'web view' notification.") + + onMainThread { + lifecycleListeners.forEach { it.onNotificationWillPresent(notification) } + } + + openNotificationActivity(activity, notification) + } + NotificationUrlResolver.UrlResolverResult.IN_APP_BROWSER -> { + NotificareLogger.debug("Resolving as 'in-app browser' notification.") + + onMainThread { + lifecycleListeners.forEach { it.onNotificationWillPresent(notification) } + } + + handleInAppBrowser(activity, notification) + } + } + } + private fun handlePassbook(activity: Activity, notification: NotificareNotification) { val integration = Notificare.loyaltyIntegration() ?: run { openNotificationActivity(activity, notification) @@ -261,7 +303,8 @@ internal object NotificarePushUIImpl : NotificareModule(), NotificarePushUI, Not } private fun handleInAppBrowser(activity: Activity, notification: NotificareNotification) { - val content = notification.content.firstOrNull { it.type == "re.notifica.content.URL" } ?: run { + val content = notification.content.firstOrNull { it.type == "re.notifica.content.URL" } + val urlStr = content?.data as? String ?: run { onMainThread { lifecycleListeners.forEach { it.onNotificationFailedToPresent(notification) } } @@ -269,8 +312,13 @@ internal object NotificarePushUIImpl : NotificareModule(), NotificarePushUI, Not return } + val url = Uri.parse(urlStr) + .buildUpon() + .removeQueryParameter("notificareWebView") + .build() + try { - createInAppBrowser().launchUrl(activity, Uri.parse(content.data as String)) + createInAppBrowser().launchUrl(activity, url) onMainThread { lifecycleListeners.forEach { it.onNotificationPresented(notification) } diff --git a/notificare-push-ui/src/main/java/re/notifica/push/ui/internal/NotificationUrlResolver.kt b/notificare-push-ui/src/main/java/re/notifica/push/ui/internal/NotificationUrlResolver.kt new file mode 100644 index 00000000..b8903aab --- /dev/null +++ b/notificare-push-ui/src/main/java/re/notifica/push/ui/internal/NotificationUrlResolver.kt @@ -0,0 +1,33 @@ +package re.notifica.push.ui.internal + +import android.net.Uri +import re.notifica.models.NotificareNotification + +internal object NotificationUrlResolver { + + internal fun resolve(notification: NotificareNotification): UrlResolverResult { + val content = notification.content.firstOrNull { it.type == "re.notifica.content.URL" } + ?: return UrlResolverResult.NONE + + val urlStr = content.data as? String + if (urlStr.isNullOrBlank()) return UrlResolverResult.NONE + + val url = Uri.parse(urlStr) + val isHttpUrl = url.scheme == "http" || url.scheme == "https" + val isDynamicLink = url.host?.endsWith("ntc.re") == true + + if (!isHttpUrl || isDynamicLink) return UrlResolverResult.URL_SCHEME + + val webViewQueryParameter = url.getQueryParameter("notificareWebView") + val isWebViewMode = webViewQueryParameter == "1" || webViewQueryParameter?.lowercase() == "true" + + return if (isWebViewMode) UrlResolverResult.WEB_VIEW else UrlResolverResult.IN_APP_BROWSER + } + + internal enum class UrlResolverResult { + NONE, + URL_SCHEME, + IN_APP_BROWSER, + WEB_VIEW, + } +} diff --git a/notificare-push-ui/src/main/java/re/notifica/push/ui/notifications/fragments/NotificareUrlFragment.kt b/notificare-push-ui/src/main/java/re/notifica/push/ui/notifications/fragments/NotificareUrlFragment.kt index 9daf88ed..8b7fc12b 100644 --- a/notificare-push-ui/src/main/java/re/notifica/push/ui/notifications/fragments/NotificareUrlFragment.kt +++ b/notificare-push-ui/src/main/java/re/notifica/push/ui/notifications/fragments/NotificareUrlFragment.kt @@ -1,6 +1,7 @@ package re.notifica.push.ui.notifications.fragments import android.annotation.SuppressLint +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,6 +13,7 @@ import re.notifica.push.ui.databinding.NotificareNotificationUrlFragmentBinding import re.notifica.push.ui.ktx.pushUIInternal import re.notifica.push.ui.notifications.fragments.base.NotificationFragment import re.notifica.push.ui.utils.NotificationWebViewClient +import re.notifica.push.ui.utils.removeQueryParameter public class NotificareUrlFragment : NotificationFragment() { @@ -42,7 +44,7 @@ public class NotificareUrlFragment : NotificationFragment() { private fun setupContent() { val content = notification.content.firstOrNull() - val url = content?.data as? String ?: run { + val urlStr = content?.data as? String ?: run { onMainThread { Notificare.pushUIInternal().lifecycleListeners.forEach { it.onNotificationFailedToPresent(notification) } } @@ -50,6 +52,12 @@ public class NotificareUrlFragment : NotificationFragment() { return } + val url = Uri.parse(urlStr) + .buildUpon() + .removeQueryParameter("notificareWebView") + .build() + .toString() + binding.webView.loadUrl(url) } } diff --git a/notificare-push-ui/src/main/java/re/notifica/push/ui/utils/Uri.kt b/notificare-push-ui/src/main/java/re/notifica/push/ui/utils/Uri.kt new file mode 100644 index 00000000..eece50d4 --- /dev/null +++ b/notificare-push-ui/src/main/java/re/notifica/push/ui/utils/Uri.kt @@ -0,0 +1,18 @@ +package re.notifica.push.ui.utils + +import android.net.Uri + +internal fun Uri.Builder.removeQueryParameter(key: String): Uri.Builder { + val uri = this.build() + + this.clearQuery() + + for (param in uri.queryParameterNames) { + if (param == key) continue + + val value = uri.getQueryParameter(param) + this.appendQueryParameter(param, value) + } + + return this +} diff --git a/notificare/src/main/java/re/notifica/internal/Version.kt b/notificare/src/main/java/re/notifica/internal/Version.kt index 32e9c3c1..a3fe689f 100644 --- a/notificare/src/main/java/re/notifica/internal/Version.kt +++ b/notificare/src/main/java/re/notifica/internal/Version.kt @@ -1,3 +1,3 @@ package re.notifica.internal -internal const val NOTIFICARE_VERSION = "3.9.1" +internal const val NOTIFICARE_VERSION = "3.10.0" diff --git a/notificare/src/main/java/re/notifica/internal/network/push/Payloads.kt b/notificare/src/main/java/re/notifica/internal/network/push/Payloads.kt index 273a3817..ee40d127 100644 --- a/notificare/src/main/java/re/notifica/internal/network/push/Payloads.kt +++ b/notificare/src/main/java/re/notifica/internal/network/push/Payloads.kt @@ -2,8 +2,10 @@ package re.notifica.internal.network.push import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import re.notifica.internal.moshi.EncodeNulls import re.notifica.models.NotificareTransport +@EncodeNulls @JsonClass(generateAdapter = true) internal data class DeviceRegistrationPayload( @Json(name = "deviceID") val deviceId: String, diff --git a/notificare/src/main/java/re/notifica/models/NotificareNotification.kt b/notificare/src/main/java/re/notifica/models/NotificareNotification.kt index 9dc68805..a3cc671b 100644 --- a/notificare/src/main/java/re/notifica/models/NotificareNotification.kt +++ b/notificare/src/main/java/re/notifica/models/NotificareNotification.kt @@ -39,6 +39,7 @@ public data class NotificareNotification( public const val TYPE_IN_APP_BROWSER: String = "re.notifica.notification.InAppBrowser" public const val TYPE_WEB_VIEW: String = "re.notifica.notification.WebView" public const val TYPE_URL: String = "re.notifica.notification.URL" + public const val TYPE_URL_RESOLVER: String = "re.notifica.notification.URLResolver" public const val TYPE_URL_SCHEME: String = "re.notifica.notification.URLScheme" public const val TYPE_IMAGE: String = "re.notifica.notification.Image" public const val TYPE_VIDEO: String = "re.notifica.notification.Video" @@ -193,6 +194,7 @@ public data class NotificareNotification( IN_APP_BROWSER, WEB_VIEW, URL, + URL_RESOLVER, URL_SCHEME, IMAGE, VIDEO, @@ -209,6 +211,7 @@ public data class NotificareNotification( TYPE_IN_APP_BROWSER -> IN_APP_BROWSER TYPE_WEB_VIEW -> WEB_VIEW TYPE_URL -> URL + TYPE_URL_RESOLVER -> URL_RESOLVER TYPE_URL_SCHEME -> URL_SCHEME TYPE_IMAGE -> IMAGE TYPE_VIDEO -> VIDEO