Foreground Lock Timeout¶
The foreground lock timeout feature automatically locks the application after a period of user inactivity while the app is in the foreground. This protects sensitive data when a user leaves the app unattended without explicitly locking or moving it to the background.
When the inactivity threshold defined in the passcode policy is reached, the SDK locks the session and presents the passcode screen, requiring the user to re-enter passcode before continuing.
Prerequisites¶
To enable this feature, the administrator must configure a Foreground Lock Timeout value under Client Settings in the mobile services cockpit.
App Level Changes¶
1. Add MyApplication.swift¶
Create a new file MyApplication.swift in your app target and subclass UIApplication to intercept touch events and report activity to the SDK.
import UIKit
import SAPFioriFlows
class MyApplication: UIApplication {
override func sendEvent(_ event: UIEvent) {
super.sendEvent(event)
// Only update last-activity time when the session is open.
// Guarding on .opened prevents the monitor running during onboarding, restore,
// or while the passcode screen is already visible (locked state).
if case .opened = OnboardingSessionManager.shared?.state {
OnboardingSessionManager.shared?.passcodePolicyManager?.manageForegroundPasscodeTimeout()
}
}
}
2. Add main.swift¶
Create a new file main.swift in your app target. This replaces the @UIApplicationMain / @main annotation.
import UIKit
import SAPFioriFlows
UIApplicationMain(
CommandLine.argc,
CommandLine.unsafeArgv,
NSStringFromClass(MyApplication.self),
NSStringFromClass(AppDelegate.self)
)
Note: Remove
@UIApplicationMainfromAppDelegate.swiftbecausemain.swiftwill serve as the entry point.
3. Add CustomPasscodePolicyManagerDelegate and Wire It in AppDelegate¶
Create a delegate class that responds when the foreground inactivity timeout elapses. It locks the session and calls unlock to present the passcode screen.
import SAPFioriFlows
import SAPCommon
class CustomPasscodePolicyManagerDelegate: PasscodePolicyManagerDelegate {
private let logger = Logger.shared(named: "SAP.Flows.CustomPasscodePolicyManagerDelegate")
func didEnforceForegroundPasscodeTimeout() {
logger.debug("Foreground timeout elapsed — locking session.")
OnboardingSessionManager.shared.lock { [weak self] lockError in
if let lockError = lockError {
self?.logger.error("lock() failed on foreground timeout.", error: lockError)
return
}
OnboardingSessionManager.shared.unlock { unlockError in
guard let unlockError = unlockError else {
return
}
AppDelegate.shared.onboardingErrorHandler?.handleUnlockingError(unlockError)
}
}
}
}
Then in AppDelegate.initializeOnboarding(), after sessionManager is created, set the delegate:
func initializeOnboarding() {
let presentationDelegate = ApplicationUIManager(window: window!)
onboardingErrorHandler = OnboardingErrorHandler()
sessionManager = OnboardingSessionManager(presentationDelegate: presentationDelegate, flowProvider: flowProvider, onboardingIDManager: MultiUserOnboardingIDManager(), delegate: onboardingErrorHandler)
presentationDelegate.showSplashScreenForOnboarding { _ in }
// Set the foreground delegate so PasscodePolicyManager can notify the app
// when the inactivity timer elapses.
let foregroundDelegate = CustomPasscodePolicyManagerDelegate()
sessionManager.passcodePolicyManager?.delegate = foregroundDelegate
onboardUser()
}
Note: The delegate must be set after
sessionManageris created. The foreground monitor itself only arms after onboarding completes, when the passcode policy is downloaded from SAP Mobile Services andinitialize(passcodePolicy:)is called internally.
visionOS App Level Changes¶
visionOS apps use SwiftUI with @main — no MyApplication.swift or main.swift is needed. Instead, use simultaneousGesture on ContentView to capture user activity.
In your App definition, update the .app case inside WindowGroup to add the gesture:
case .app:
ContentView()
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in
if case .opened = OnboardingSessionManager.shared?.state {
OnboardingSessionManager.shared?.passcodePolicyManager?.manageForegroundPasscodeTimeout()
}
}
)
Note: The
.openedstate guard ensures the monitor is only updated when the session is active — not during onboarding, restore, or while the passcode screen is visible.
The CustomPasscodePolicyManagerDelegate setup in AppDelegate.initializeOnboarding() is the same as for apps using UIApplication (Step 3 above).