ARTICLE AD BOX
This is a known challenge with Android's Scoped Storage and how modern keyboards like Gboard manage their own internal "history stacks" independently of the system's primary clip.
Here is the best approach to mitigate this for Android 12 (API 31) and higher.
1. Flag Data as "Sensitive" (The Official Fix)
Starting in Android 12/13, Google introduced a specific flag to tell keyboards and the system UI that a piece of data is sensitive. When this flag is set, Gboard is supposed to not show the text in the suggestion bar and should visually obfuscate it in the history.
Kotlin Implementation:
Kotlin
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clipData = ClipData.newPlainText("password", sensitiveText) // Flag the content as sensitive clipData.description.extras = PersistableBundle().apply { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true) } else { putBoolean("android.content.extra.IS_SENSITIVE", true) } } clipboard.setPrimaryClip(clipData)2. Use clearPrimaryClip() instead of Empty String
Setting an empty string via setPrimaryClip(ClipData.newPlainText("", "")) actually adds a new item to the history. If you are on API 28+, you should use the explicit clear method, though even this sometimes fails to trigger a "delete" in Gboard's local cache.
Kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { clipboardManager.clearPrimaryClip() } else { clipboardManager.setPrimaryClip(ClipData.newPlainText("", "")) }3. Use textNoSuggestions on Input Fields
The keyboard doesn't just cache from the clipboard; it also caches from the predictive text engine. To prevent Gboard from "learning" sensitive words typed into your app, ensure your EditText or TextField uses:
XML: android:inputType="textNoSuggestions|textPassword"
Compose: keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
