Random 或 SecureRandom 從字元池抽取 N 個字元(通常 4-6 位)。Bitmap.createBitmap(width, height, Config.ARGB_8888)。Canvas,繪製背景色、干擾線、干擾點、噪點。Paint(字型、大小、顏色、斜度、粗細),逐字元繪製於隨機位置、旋轉角度。Bitmap 壓縮為 JPEG/PNG 位元組陣列,回傳前端 ImageView 顯示。SharedPreferences、MemoryCache 或後端 Session,並設定過期時間(如 60 秒)。ImageView 設定 OnClickListener,重新呼叫生成流程並更新圖片與快取。// 生成隨機驗證碼字串
private String generateCode(int length) {
String pool = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";
SecureRandom rnd = new SecureRandom();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) sb.append(pool.charAt(rnd.nextInt(pool.length())));
return sb.toString();
}
// 繪製干擾圖片
private Bitmap drawCaptcha(String code, int width, int height) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setTextSize(60f);
paint.setAntiAlias(true);
Random rnd = new Random();
// 干擾線
for (int i = 0; i < 5; i++) {
paint.setColor(Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)));
canvas.drawLine(rnd.nextInt(width), rnd.nextInt(height), rnd.nextInt(width), rnd.nextInt(height), paint);
}
// 字元
for (int i = 0; i < code.length(); i++) {
paint.setColor(Color.argb(255, rnd.nextInt(128), rnd.nextInt(128), rnd.nextInt(128)));
paint.setTextSkewX(rnd.nextFloat() * 0.5f - 0.25f);
canvas.drawText(String.valueOf(code.charAt(i)), 30 + i * 50, 70, paint);
}
return bitmap;
}
Path 繪製貝茲曲線干擾線,提高機器識別難度。純客戶端生成驗證碼 不可用於高安全場景(登入、支付、註冊),必須由後端生成、前端展示、後端驗證,防止繞過驗證邏輯。