Implementing Clipboard Integration in a Mobile App
Clipboard is one of those APIs that seems trivial until you encounter its behavior across iOS and Android versions. Starting with iOS 14, each access to UIPasteboard.general without permission shows a system banner "[App] pasted from clipboard." Android 12+ has similar toast. Not a bug—intentional platform behavior.
iOS: UIPasteboard and Limitations
UIPasteboard.general.string is synchronous reading. But from iOS 14, the app gets a warning on each read if not initiated by explicit user action (pressing "Paste" button).
Correct approach—use UIPasteControl (iOS 16+): system button that reads clipboard without warning because user explicitly tapped it:
let pasteControl = UIPasteControl(configuration: UIPasteControl.Configuration())
pasteControl.target = self
// implement UIPasteConfigurationSupporting
override func paste(itemProviders: [NSItemProvider]) {
for provider in itemProviders {
if provider.canLoadObject(ofClass: NSString.self) {
provider.loadObject(ofClass: NSString.self) { string, _ in
DispatchQueue.main.async {
self.handlePastedText(string as? String)
}
}
}
}
}
For iOS 14–15 where UIPasteControl unavailable, only read clipboard in applicationDidBecomeActive or on explicit tap to avoid banner. Reading in viewDidLoad or in background—guaranteed banner.
Writing to clipboard—no restrictions: UIPasteboard.general.string = "text". For complex content (image + text), use setItems([["public.plain-text": text, "public.png": imageData]]) with explicit UTI types.
Android: ClipboardManager
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
// Write
val clip = ClipData.newPlainText("label", "text to copy")
clipboard.setPrimaryClip(clip)
// Read
val text = clipboard.primaryClip?.getItemAt(0)?.coerceToText(context)
On Android 13+ (API 33), ClipboardManager.getPrimaryClip() returns data only to foreground app or the app that wrote it. Background read—SecurityException. This change broke several password managers on update.
Android 13 added visual confirmation on copy—system toast with copied text preview. App can disable it for specific operation: ClipData.newPlainText("label", text).apply { description.extras = PersistableBundle().apply { putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true) } }—for sensitive data (passwords), toast doesn't show.
Flutter and React Native
In Flutter—flutter/services package, Clipboard.getData(Clipboard.kTextPlain) and Clipboard.setData(). Returns Future—don't call in initState without mounted check, or setState after dispose gives assertion error.
In React Native—@react-native-clipboard/clipboard. On iOS wraps UIPasteboard, on Android ClipboardManager. Issue: package doesn't abstract iOS 16 UIPasteControl—needs native module if necessary.
Clipboard integration implementation considering iOS 14+ and Android 13+: 1 day. Cost calculated individually.







