Nút “Sao chép mã” thường chỉ cần vài dòng code, nhưng trải nghiệm có thể bị lặp thông báo trên thiết bị mới. Android 13 có phản hồi hệ thống khi nội dung được đưa vào clipboard; nếu ứng dụng luôn hiện thêm Toast, người dùng có thể thấy hai lời xác nhận cho cùng một lần bấm.
Bài dùng mã giả DEMO-123, dành cho dự án Android Kotlin đã có Activity. Tài liệu ClipboardManager, ClipData và hướng dẫn copy/paste được đối chiếu ngày 28/10/2026. Lượt biên tập chỉ rà code và kiểm tra XML resource, chưa build APK hoặc thử trên thiết bị.
1. Tách label khỏi nội dung được dán
ClipData.newPlainText(label, text) tạo dữ liệu text. Label mô tả loại nội dung cho giao diện, còn text là giá trị thực sự được sao chép. Đừng đặt lời “Đã sao chép” vào tham số text nếu mục tiêu là sao chép mã đơn.
ClipboardManager.setPrimaryClip đặt clip hiện tại. Nó không nối thêm vào lịch sử do ứng dụng của bạn quản lý và cũng không xác nhận người dùng đã dán ở nơi nhận. Hành động copy và hành động paste là hai thời điểm riêng.
2. Một helper gọi từ Activity
Thêm hàm vào package của dự án. Ví dụ dùng API cơ bản có từ trước các phiên bản Android hiện hành; dự án có thể dùng minSdk 21 trở lên và compileSdk phù hợp môi trường của nhóm.
import android.app.Activity
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Build
import android.widget.Toast
fun Activity.copyDemoCode(code: String) {
require(code.isNotBlank()) { "Code must not be blank" }
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(getString(R.string.copy_code_label), code)
clipboard.setPrimaryClip(clip)
if (Build.VERSION.SDK_INT < 33) {
Toast.makeText(this, R.string.code_copied, Toast.LENGTH_SHORT).show()
}
}
Nhánh dưới API 33 giữ phản hồi của ứng dụng cho Android 12L và cũ hơn. Với Android 13 trở lên, ví dụ không thêm Toast riêng cho lần copy này, theo hướng dẫn tránh thông báo trùng của Android.
Đây không phải cam kết rằng giao diện clipboard của mọi hãng và mọi phiên bản giống hệt nhau. Hãy kiểm tra trên các phiên bản sản phẩm hỗ trợ, thay vì dùng screenshot của một máy làm tiêu chuẩn cho toàn bộ hệ sinh thái.
3. Thêm resource và gắn vào thao tác bấm
Trong res/values/strings.xml, thêm hai chuỗi vào phần tử resources đang có:
<resources>
<string name="copy_code_label">Mã minh họa</string>
<string name="code_copied">Đã sao chép mã.</string>
</resources>
Từ callback bấm của Activity, gọi:
copyDemoCode("DEMO-123")
Giữ nguyên chuỗi người dùng định sao chép; hàm chỉ kiểm tra không rỗng, không tự trim hoặc đổi chữ hoa. Nếu sản phẩm có quy tắc định dạng mã, hãy làm rõ nó ở tầng dữ liệu trước khi hiển thị và copy.
Không đặt lời gọi copy vào onCreate hoặc luồng tự chạy mỗi lần màn hình xuất hiện. Người dùng cần biết hành động nào đưa nội dung vào clipboard. Ví dụ cũng không đọc clipboard nền hoặc xây một dịch vụ theo dõi nội dung được sao chép từ ứng dụng khác.
4. Kiểm tra bằng nơi dán đơn giản
Trên thiết bị thử nghiệm, bấm nút rồi dán vào một ô nhập text. Nội dung phải là DEMO-123, không phải label “Mã minh họa” hoặc thông báo xác nhận. Thử thêm tiếng Việt, dòng mới và khoảng trắng có chủ ý nếu sản phẩm cho phép các giá trị đó.
Kiểm tra riêng một máy API 32 trở xuống và một máy API 33 trở lên. Ở nhóm cũ, xác nhận phản hồi của ứng dụng xuất hiện sau copy. Ở nhóm mới, xem có còn Toast hoặc Snackbar riêng từ một lớp helper khác khiến thông báo bị lặp hay không.
Nếu đang có một hàm copy dùng chung, rà tất cả nơi gọi trước khi thêm Toast ở màn hình. Hai lớp cùng chịu trách nhiệm phản hồi là một nguyên nhân thực tế khiến bạn thấy lặp thông báo ngay cả trước Android 13.
Lỗi thường gặp và giới hạn
Nhầm thứ tự label và text có thể làm code vẫn biên dịch nhưng người dùng dán sai dữ liệu. Một kiểm tra đơn giản ở ô nhập ngoài ứng dụng sẽ phát hiện điều này rõ hơn việc chỉ nhìn Toast.
Nếu áp dụng cho nội dung nhạy cảm, cần đọc phần đánh dấu sensitive content trong hướng dẫn Android và thiết kế chính sách phù hợp; ví dụ chỉ dùng mã giả, không triển khai quy trình copy token hoặc mật khẩu. Không ghi nội dung clipboard thật vào log để chứng minh tính năng hoạt động.
Helper không lưu dữ liệu bền vững, không quản lý lịch sử và không hứa rằng clipboard sẽ giữ mã mãi. Mục tiêu hẹp là đưa đúng text vào clipboard từ một thao tác rõ ràng và phản hồi phù hợp phiên bản. Hoàn tất kiểm tra thiết bị trước khi dùng nó trong luồng sản phẩm.


