Was funktioniert:
Android – Die Verwendung von FLAG_SECURE funktioniert perfekt:
Code: Select all
actual fun disableScreenshots() {
try {
val activity = activityProvider.invoke() ?: return
activity.window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
} catch (e: Exception) {
logDebug("error disabling screenshots: ${e.message}")
}
}
actual fun enableScreenshots() {
try {
val activity = activityProvider.invoke() ?: return
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
} catch (e: Exception) {
logDebug("error enabling screenshots: ${e.message}")
}
}
iOS – Ich habe die übliche Problemumgehung für sichere UITextField-Einträge ausprobiert, aber sie beschädigt die Benutzeroberfläche, wenn versucht wird, den Normalzustand wiederherzustellen:
Code: Select all
actual fun disableScreenshots() {
try {
val window: UIWindow? = UIApplication.sharedApplication.keyWindow
if (secureTextField == null && window != null) {
val textField = UITextField()
textField.setSecureTextEntry(true)
textField.setUserInteractionEnabled(false)
val placeholderView = UIView(frame = textField.frame)
val imageView = UIImageView()
imageView.setFrame(UIScreen.mainScreen.bounds)
imageView.backgroundColor = platform.UIKit.UIColor.blackColor
placeholderView.addSubview(imageView)
window.addSubview(textField)
textField.setLeftView(placeholderView)
textField.setLeftViewMode(UITextFieldViewMode.UITextFieldViewModeAlways)
val superlayer = window.layer.superlayer
if (superlayer != null) {
superlayer.addSublayer(textField.layer)
val sublayers = textField.layer.sublayers
if (sublayers != null) {
val sublayerCount = sublayers.count().toInt()
if (sublayerCount > 0) {
val lastIndex = sublayerCount - 1
val lastLayer = sublayers[lastIndex] as? platform.QuartzCore.CALayer
lastLayer?.addSublayer(window.layer)
}
}
}
secureTextField = textField
}
} catch (e: Exception) {
logDebug("error disabling screenshots: ${e.message}")
}
}
actual fun enableScreenshots() {
try {
secureTextField?.let { textField ->
val window: UIWindow? = UIApplication.sharedApplication.keyWindow
window?.layer?.superlayer?.addSublayer(window.layer)
textField.setSecureTextEntry(false)
textField.setLeftView(null)
textField.layer.removeFromSuperlayer()
textField.removeFromSuperview()
}
secureTextField = null
} catch (e: Exception) {
logDebug("error enabling screenshots: ${e.message}")
}
}
- UITextField-Ansatz aus diesem Medium-Artikel
- Lösungen aus diesem StackOverflow-Thread – alle verwenden den gleichen UITextField-Trick
- ScreenshotPreventing-iOS-Repo – verwenden Sie denselben UITextField-Trick
Wenn enableScreenshots() aufgerufen wird (Benutzer navigiert vom QR-Bildschirm weg), wird die Fensterebene aus der Ansichtshierarchie verwaist, was dazu führt, dass die gesamte Benutzeroberfläche nicht mehr gerendert wird.
Hinweis: Ich bin relativ neu in der Compose Multiplatform- und iOS-Entwicklung, daher ist es möglich, dass meine Implementierung Probleme mit der Verwaltung der Ebenenhierarchie hat. Wenn es einen besseren Ansatz gibt oder wenn ich etwas grundlegend falsch mache, würde ich mich über jede Anleitung freuen.
Fragen:
- Gibt es eine zuverlässige Möglichkeit, Screenshots auf iOS in Kotlin Multiplatform zu verhindern oder bei der Aufnahme von Screenshots einen schwarzen Bildschirm anzuzeigen (wie es bei Banking-Apps/Netflix der Fall ist), ohne die Benutzeroberfläche zu beschädigen?
- Hat jemand dies erfolgreich in Compose Multiplatform für iOS implementiert?
- Wenn meine Implementierung fehlerhaft ist, wie kann ich die Fensterebenenhierarchie nach dem Entfernen des sicheren Textfelds richtig wiederherstellen?
- Compose Multiplatform: 1.9.3
- Kotlin: 2.1.0
- Ziel: iOS 13+
Mobile version