diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/ViewUtils.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/ViewUtils.kt index 0a3867fbf4..16324c9c9e 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/ViewUtils.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/ViewUtils.kt @@ -9,6 +9,7 @@ import android.graphics.Rect import android.os.Build import android.view.View import android.view.Window +import android.view.WindowManager import kotlin.math.roundToInt object ViewUtils { @@ -19,19 +20,32 @@ object ViewUtils { // Due to differences in accounting for keyboard, navigation bar, and status bar between // Android versions have different implementation here fun getWindowHeight(activity: Activity): Int { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + getWindowHeightAPI30Plus(activity) + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { getWindowHeightAPI23Plus(activity) } else { getWindowHeightLollipop(activity) } } + @Suppress("DEPRECATION") private fun getDisplaySizeY(activity: Activity): Int { val point = Point() activity.windowManager.defaultDisplay.getSize(point) return point.y } + @TargetApi(Build.VERSION_CODES.R) + private fun getWindowHeightAPI30Plus(activity: Activity): Int { + val windowMetrics = activity.windowManager.currentWindowMetrics + val insets = + windowMetrics.windowInsets.getInsetsIgnoringVisibility( + android.view.WindowInsets.Type.systemBars(), + ) + return windowMetrics.bounds.height() - insets.top - insets.bottom + } + // Requirement: Ensure DecorView is ready by using OSViewUtils.decorViewReady @TargetApi(Build.VERSION_CODES.M) private fun getWindowHeightAPI23Plus(activity: Activity): Int { @@ -87,7 +101,10 @@ object ViewUtils { } fun getFullbleedWindowWidth(activity: Activity): Int { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val windowMetrics = activity.windowManager.currentWindowMetrics + windowMetrics.bounds.width() + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { val decorView = activity.window.decorView decorView.width } else { @@ -96,6 +113,20 @@ object ViewUtils { } fun getWindowWidth(activity: Activity): Int { - return getWindowVisibleDisplayFrame(activity).width() + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + getWindowWidthAPI30Plus(activity) + } else { + getWindowVisibleDisplayFrame(activity).width() + } + } + + @TargetApi(Build.VERSION_CODES.R) + private fun getWindowWidthAPI30Plus(activity: Activity): Int { + val windowMetrics = activity.windowManager.currentWindowMetrics + val insets = + windowMetrics.windowInsets.getInsetsIgnoringVisibility( + android.view.WindowInsets.Type.systemBars(), + ) + return windowMetrics.bounds.width() - insets.left - insets.right } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/application/impl/ApplicationService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/application/impl/ApplicationService.kt index 55f2612324..88af4327f9 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/application/impl/ApplicationService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/application/impl/ApplicationService.kt @@ -83,6 +83,9 @@ class ApplicationService() : IApplicationService, ActivityLifecycleCallbacks, On val configuration = object : ComponentCallbacks { + private var lastScreenWidthDp: Int = 0 + private var lastScreenHeightDp: Int = 0 + override fun onConfigurationChanged(newConfig: Configuration) { // If Activity contains the configChanges orientation flag, re-create the view this way if (current != null && @@ -93,6 +96,27 @@ class ApplicationService() : IApplicationService, ActivityLifecycleCallbacks, On ) { onOrientationChanged(newConfig.orientation, current!!) } + + // Handle foldable device screen size changes (fold/unfold events) + // Foldable devices trigger CONFIG_SCREEN_SIZE without orientation change + if (current != null && hasScreenSizeChanged(newConfig)) { + Logging.debug( + "ApplicationService.onConfigurationChanged: Screen size changed " + + "(foldable device fold/unfold detected) - " + + "width: ${newConfig.screenWidthDp}dp, height: ${newConfig.screenHeightDp}dp", + ) + onScreenSizeChanged(current!!) + } + lastScreenWidthDp = newConfig.screenWidthDp + lastScreenHeightDp = newConfig.screenHeightDp + } + + private fun hasScreenSizeChanged(newConfig: Configuration): Boolean { + if (lastScreenWidthDp == 0 && lastScreenHeightDp == 0) { + return false + } + return newConfig.screenWidthDp != lastScreenWidthDp || + newConfig.screenHeightDp != lastScreenHeightDp } override fun onLowMemory() {} @@ -368,6 +392,23 @@ class ApplicationService() : IApplicationService, ActivityLifecycleCallbacks, On handleFocus() } + /** + * Handles screen size changes that occur on foldable devices when folding/unfolding. + * Unlike orientation changes, foldable devices can change screen dimensions significantly + * without changing orientation (e.g., Samsung Galaxy Fold going from cover screen to main screen). + * This triggers the same view recreation flow as orientation changes to ensure IAMs are + * properly resized and repositioned. + */ + private fun onScreenSizeChanged(activity: Activity) { + // Remove view + activityLifecycleNotifier.fire { it.onActivityStopped(activity) } + + // Show view with new dimensions + activityLifecycleNotifier.fire { it.onActivityAvailable(activity) } + + activity.window.decorView.viewTreeObserver.addOnGlobalLayoutListener(this) + } + private fun handleLostFocus() { if (isInForeground) { Logging.debug("ApplicationService.handleLostFocus: application is now out of focus") diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt index d509b9494c..5ddc09a72e 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt @@ -263,7 +263,7 @@ internal class WebViewManager( showMessageView(lastPageHeight) } } else { - // Activity rotated + // Activity rotated or screen size changed (e.g., foldable device fold/unfold) calculateHeightAndShowWebViewAfterNewActivity() } }