Uncategorized

Tự Làm App Quản Lý Chi Tiêu Android Bằng QR & Giọng Nói

Lập Trình Di Động & Kinh Tế Dữ Liệu Hành Vi (Data-Driven Apps)

Tự Làm App Quản Lý Chi Tiêu Android Bằng QR & Giọng Nói

Rào cản lớn nhất khiến hơn 80% người dùng từ bỏ các ứng dụng sổ thu chi sau 1 tuần sử dụng chính là sự phiền toái khi phải mở app và gõ từng con số thủ công. Làm thế nào để khi người dùng vừa quét mã QR tại quầy thanh toán, ứng dụng tự động “bắt” được số tiền mà không cần nhập lại? Làm sao để người dùng chỉ cần nói một câu đời thường như “mua 1 bát phở 50 ca” hay “sáng nay cf hết 35k”, app tự động bóc tách thành bản ghi chuẩn mực? Bài viết này là cẩm nang phân tích kiến trúc chuyên sâu, cung cấp toàn bộ mã nguồn Kotlin thực chiến và chiến lược kiếm tiền từ quảng cáo dựa trên thói quen tiêu dùng ẩn danh chuẩn chính sách Google Play.

Chuyên mục: Android Engineering, NLP & Fintech Automation
•
Thời gian đọc: 22 phút chuyên sâu
•
Công nghệ lõi: Android Kotlin, NotificationListenerService, Overlay Dialog, Room Database, Regex NLP

Người dùng thực hiện thanh toán qua điện thoại thông minh bằng mã QR và giọng nói

Hình 1: Tự động hóa trải nghiệm ghi chép chi tiêu bằng thanh toán mã QR và giọng nói giúp giải phóng thao tác gõ phím thủ công.

Tóm Tắt Điểm Cốt Lõi (Executive Summary)

• Rào cản Sandbox và giải pháp VietQR: App thứ ba không thể “nhìn lén” màn hình quét QR của app ngân hàng do cơ chế bảo mật cô lập tiến trình (Sandbox). Giải pháp tối ưu số 1 trên Android là sử dụng NotificationListenerService để bắt thông báo biến động số dư tức thời từ Techcombank, Vietcombank, MBBank… kết hợp cửa sổ nổi WindowManager Overlay để người dùng chỉ chạm 1 lần là lưu xong.
• Nhập liệu giọng nói tiếng lóng (ASR + Regex NLP): Sử dụng Android SpeechRecognizer thu âm thành chữ, sau đó dùng bộ phân tích biểu thức chính quy (Regex) để quy đổi các từ lóng dân gian: ca, k → ×1.000; loét, lét → ×100.000; củ, triệu → ×1.000.000.
• Mô hình kinh doanh Data Monetization: Miễn phí hoàn toàn cho người dùng, kiếm tiền từ ngân sách quảng cáo của doanh nghiệp thông qua hệ thống gắn thẻ chân dung người dùng (User Persona Tagging: MOM_AND_BABY, COFFEE_LOVER) và đồng bộ ẩn danh tuyệt đối qua Google Advertising ID (AAID).

Mục Lục Toàn Cảnh Kỹ Thuật Xây Dựng Ứng Dụng Quản Lý Chi Tiêu:
  • Phần 1: Phân Tích Tính Khả Thi: Lấy Số Tiền Quét Mã QR Ngân Hàng (Rào Cản Sandbox vs Lắng Nghe Notification)
  • Phần 2: Phân Tích Phương Án Giọng Nói: Xây Dựng Bộ ASR & NLP Xử Lý Tiếng Lóng Tiếng Việt (“k”, “ca”, “củ”)
  • Phần 3: So Sánh 2 Phương Án: Tự Động Bắt QR vs Nhập Liệu Giọng Nói Đa Vùng Miền
  • Phần 4: Sơ Đồ Pipeline & Luồng Dữ Liệu Thực Thi Trên Hệ Điều Hành Android
  • Phần 5: Mã Nguồn Kotlin 1: Module Phân Tách Ngôn Ngữ Tự Nhiên (TransactionParser.kt)
  • Phần 6: Mã Nguồn Kotlin 2: Service Lắng Nghe Thông Báo Biến Động Số Dư (BankNotificationListener.kt)
  • Phần 7: Mã Nguồn Kotlin 3: Cửa Sổ Nổi Thông Minh Hiện Ngay Sau Khi Quẹt Tiền (QuickExpenseOverlay.kt)
  • Phần 8: Thiết Kế Cơ Sở Dữ Liệu Room SQLite: Hệ Thống Gắn Thẻ Hành Vi (Behavioral Tags Entity)
  • Phần 9: Chiến Lược Khai Thác Big Data Ẩn Danh & Quy Trình Vượt Kiểm Duyệt Google Play Store
  • Phần 10: Câu Hỏi Thường Gặp (FAQ Tối Ưu Cho AI Overview & Trợ Lý Tìm Kiếm)

1. Phân Tích Tính Khả Thi: Lấy Số Tiền Quét Mã QR Ngân Hàng

Ý tưởng để một ứng dụng quản lý chi tiêu tự động “biết” người dùng vừa chi bao nhiêu tiền khi họ quét mã thanh toán tại nhà hàng hay quán cà phê là bài toán hấp dẫn nhất. Tuy nhiên, trước khi viết code, bạn cần hiểu rõ ranh giới bảo mật của hệ điều hành:

Rào cản Sandbox: Không thể can thiệp khi người dùng mở App Ngân hàng

Cả Android và iOS đều áp dụng kiến trúc Application Sandbox: Mỗi ứng dụng chạy trong một tiến trình hoàn toàn cô lập, gán một UID riêng biệt. Ứng dụng của bạn tuyệt đối không thể chạy ngầm để theo dõi camera, chụp màn hình hay đọc dữ liệu quét mã bên trong ứng dụng Vietcombank, Techcombank, MBBank hay MoMo. Mọi nỗ lực can thiệp bộ nhớ ứng dụng khác đều bị hệ điều hành chặn đứng hoặc Google Play quét xóa app ngay lập tức.

Bản chất mã VietQR (Chuẩn EMVCo tại Việt Nam)

Khi quét mã QR thanh toán tại quầy, chuỗi văn bản dịch ra thực chất là định dạng chuẩn hóa (TLV – Tag Length Value) chứa các trường dữ liệu:

  • Mã định danh ngân hàng (BIN): Ví dụ 970436 (Vietcombank), 970407 (Techcombank).
  • Số tài khoản người thụ hưởng: Dãy số tài khoản của chủ quán.
  • Số tiền thanh toán: Có thể có sẵn (mã QR động tạo từ máy POS) hoặc để trống (mã QR tĩnh in trên mica bắt khách tự điền).

Giải pháp tối ưu số 1: Lắng nghe thông báo biến động số dư (Push Notification)

Thay vì can thiệp vào hành vi quét mã phức tạp, giải pháp chuẩn công nghiệp (được các app lớn như Money Lover, Sổ Thu Chi áp dụng) là: Người dùng cứ quét QR và chuyển tiền bằng app ngân hàng của họ như bình thường. Ngay khi giao dịch hoàn tất, app ngân hàng sẽ đẩy một thông báo biến động số dư lên màn hình (ví dụ: “TK 190… BDO: -50,000VND…”). Trên Android, app của bạn sử dụng quyền NotificationListenerService để tự động “bắt” gói tin này, bóc tách chính xác số tiền và kích hoạt Pop-up để người dùng xác nhận chỉ với một cú chạm.

2. Phân Tích Phương Án Giọng Nói: Bộ ASR & NLP Xử Lý Tiếng Lóng

Nhập liệu bằng giọng nói (Voice Input) là phương án tuyệt vời nhất về mặt trải nghiệm: Người dùng vừa bước ra khỏi quán chỉ cần giữ phím micro và nói một câu tự nhiên. Để xử lý thành công câu nói “mua 1 bát phở 50 ca” thành bản ghi Chi | 50.000đ | 1 bát phở, hệ thống cần 2 bước xử lý liên hoàn:

1. Bước Chuyển Âm Thanh Thành Chữ (ASR – Automated Speech Recognition)

Trên Android, bạn có 2 lựa chọn triển khai:

  • Thư viện gốc SpeechRecognizer của Android (Khuyên dùng): Tận dụng cỗ máy nhận dạng giọng nói tích hợp sẵn của Google trên máy. Hoàn toàn miễn phí, tốc độ phản hồi tức thì và không làm tốn chi phí máy chủ API.
  • API Cloud ngoại vi (OpenAI Whisper / Google Speech API): Độ chính xác cao hơn với giọng đọc địa phương cực nặng, nhưng tốn phí duy trì API hàng tháng, không phù hợp cho mô hình ứng dụng cộng đồng miễn phí ban đầu.

2. Bước Xử Lý Ngôn Ngữ Tự Nhiên & Từ Điển Tiếng Lóng (NLP & Regex Normalizer)

Người Việt rất hiếm khi nói “năm mươi nghìn đồng”, mà thường sử dụng tiếng lóng. Bạn cần xây dựng bộ quy tắc ánh xạ (Mapping Rules):

• “ca”, “k”, “nghìn”, “ngàn” → Hệ số nhân: × 1.000
• “loét”, “lét”, “trăm” → Hệ số nhân: × 100.000
• “củ”, “triệu”, “tr” → Hệ số nhân: × 1.000.000

Bên cạnh đó, bộ lọc sẽ phân loại ý định (Intent): Các từ khóa “mua, ăn, chi, trả, hết, mất, cà thẻ” được xếp vào nhóm CHI; các từ khóa “nhận, lương, thưởng, bán, được, đòi nợ” được xếp vào nhóm THU.

Bảng phân tích trực quan dữ liệu chi tiêu cá nhân trên biểu đồ thiết bị di động

Hình 2: Biến dữ liệu giao dịch rời rạc thành báo cáo tài chính thông minh phục vụ quản lý ngân sách cá nhân.

3. Bảng So Sánh Toàn Diện: Bắt QR Thông Báo vs Nhập Giọng Nói

Tiêu Chí Kỹ Thuật Phương Án Bắt QR Qua Notification Phương Án Nhập Bằng Giọng Nói (ASR)
Cơ chế kích hoạt Hoàn toàn thụ động (Tự nổi Pop-up sau khi giao dịch) Chủ động (Bấm giữ micro và nói câu thoại)
Độ chính xác số tiền Tuyệt đối 100% (Đọc từ tin nhắn biến động số dư) Phụ thuộc vào âm lượng & phát âm người dùng
Nội dung chi tiết Chỉ có thông tin chuyển khoản chung chung (cần user điền thêm) Rất chi tiết (“bát phở tái nạm”, “cà phê sữa đá”)
Độ khó lập trình Trung bình (cần viết regex phân loại nhiều ngân hàng) Thấp đến trung bình (dùng Android component)
Duyệt chợ ứng dụng Phải giải trình quyền NotificationListener với Google Dễ dàng vượt qua kiểm duyệt 100%

4. Sơ Đồ Pipeline & Luồng Dữ Liệu Thực Thi Trên Android

Sơ đồ dưới đây mô tả cách hai kênh dữ liệu (Thông báo ngân hàng và Giọng nói) cùng hội tụ về cơ sở dữ liệu SQLite cục bộ, chuẩn bị cho bài toán gắn thẻ hành vi quảng cáo:

[SƠ ĐỒ KIẾN TRÚC TOÀN DIỆN APP CHI TIÊU THÔNG MINH ANDROID]
[KÊNH 1: QUÉT QR NGÂN HÀNG] [KÊNH 2: GIỌNG NÓI ĐỜI THƯỜNG] Khách quét VietQR tại quầy Khách nói: “Mua 1 bát phở 50 ca”
│ │
▼ ▼
[App Ngân Hàng Đẩy Thông Báo] [Android SpeechRecognizer Component] “TK 190… BDO: -50,000VND…” │
│ ▼
▼ [Chuỗi Text Thô Tiếng Việt] [NotificationListenerService] │
│ ▼
▼ [TransactionParser.kt (Regex NLP)] [Bóc Tách Regex: 50.000đ] – ca/k → 50.000đ | Mua → CHI | Phở
│ │
└───────────────────────┬────────────────────────┘
│
▼
[QuickExpenseOverlay.kt (Cửa Sổ Nổi)] – Điền sẵn: 50.000đ
– Gợi ý danh mục: Ăn uống (Food & Beverage)
– Khách chạm 1 lần “Lưu Ngay”
│
▼
[CƠ SỞ DỮ LIỆU CỤC BỘ (ROOM SQLITE)] ├── TransactionEntity (Lưu chi tiết khoản chi thô)
└── BehaviorTagEntity (Tự động cộng điểm Persona [DINING_OUT])
│
▼ (Định kỳ đồng bộ tuần)
[ĐỒNG BỘ ẨN DANH QUA CLOUD API] – Gửi kèm: Google Advertising ID (AAID)
– Payload: Danh sách thẻ [COFFEE_LOVER: 15đ, DINING_OUT: 30đ] – Doanh nghiệp khớp lệnh hiển thị Banner đúng nhu cầu thực tế!

5. Mã Nguồn Kotlin 1: Module Phân Tách Ngôn Ngữ (TransactionParser.kt)

Đây là trái tim xử lý chuỗi ký tự nhận diện giọng nói hoặc tin nhắn thông báo ngân hàng. File được thiết kế dưới dạng Singleton Object để tái sử dụng ở mọi nơi trong dự án Android:

package com.yourdomain.expenseapp.utils

import java.util.regex.Pattern

data class ParsedTransaction(
    val type: String,       // "CHI" hoặc "THU"
    val amount: Long,       // Số tiền nguyên bản chuẩn hóa
    val content: String     // Nội dung giao dịch đã làm sạch
)

object TransactionParser {

    fun parse(input: String): ParsedTransaction {
        val rawText = input.lowercase().trim()

        // 1. Phân loại loại giao dịch (Intent Classification)
        val thuKeywords = listOf("nhận", "lương", "thưởng", "thu", "bán", "được", "hoàn tiền")
        val type = if (thuKeywords.any { rawText.contains(it) }) "THU" else "CHI"

        // 2. Regex bóc tách số tiền và đơn vị tiếng lóng (Regex Entity Extractor)
        // Bắt các mẫu: 50k, 50 ca, 100 loét, 2 củ, 15 triệu, 30 ngàn...
        val moneyPattern = Pattern.compile("(\d+)\s*(k|ca|nghìn|ngàn|loét|lét|trăm|củ|triệu|tr)")
        val matcher = moneyPattern.matcher(rawText)

        var amount: Long = 0
        var matchedText = ""

        if (matcher.find()) {
            val numberStr = matcher.group(1) ?: "0"
            val unitStr = matcher.group(2) ?: ""
            matchedText = matcher.group(0) ?: ""

            val baseNumber = numberStr.toLongOrNull() ?: 0L

            // Nhân hệ số tương ứng theo tiếng lóng Việt Nam
            amount = when (unitStr) {
                "k", "ca", "nghìn", "ngàn" -> baseNumber * 1_000L
                "loét", "lét", "trăm"      -> baseNumber * 100_000L
                "củ", "triệu", "tr"        -> baseNumber * 1_000_000L
                else                      -> baseNumber
            }
        } else {
            // Trường hợp đọc số thuần không có đơn vị (ví dụ tin nhắn SMS: "-50,000VND")
            val cleanDigits = rawText.replace("[^0-9]".toRegex(), "")
            if (cleanDigits.isNotEmpty()) {
                amount = cleanDigits.toLongOrNull() ?: 0L
            }
        }

        // 3. Trích xuất nội dung bằng cách loại bỏ số tiền và các hư từ thừa
        var content = rawText
        if (matchedText.isNotEmpty()) {
            content = content.replace(matchedText, "")
        }

        val stopWords = listOf("mua", "ăn", "chi", "trả", "hết", "mất", "vừa", "nhận", "được", "tiền", "vnd", "đ")
        for (word in stopWords) {
            content = content.replace("\b$word\b".toRegex(), "")
        }

        content = content.replace("\s+".toRegex(), " ").trim()
        content = content.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }

        if (content.isEmpty()) {
            content = if (type == "CHI") "Khoản chi tiêu" else "Khoản thu nhập"
        }

        return ParsedTransaction(type, amount, content)
    }
}

6. Mã Nguồn Kotlin 2: Service Lắng Nghe Thông Báo (BankNotificationListener.kt)

Để nhận diện biến động số dư từ các app ngân hàng tại Việt Nam, bạn cần đăng ký quyền dịch vụ hệ thống và bóc tách nội dung thông báo:

package com.yourdomain.expenseapp.services

import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import com.yourdomain.expenseapp.utils.QuickExpenseOverlay
import com.yourdomain.expenseapp.utils.TransactionParser

class BankNotificationListener : NotificationListenerService() {

    // Danh sách định danh Package Name của các ứng dụng ngân hàng và ví điện tử phổ biến
    private val bankPackages = mapOf(
        "com.technext.techcombank" to "Techcombank",
        "com.vietcombank.android"  to "Vietcombank",
        "com.mbmobile"             to "MBBank",
        "vn.com.vpb.fpt"           to "VPBank",
        "com.vng.momo"             to "Ví MoMo"
    )

    override fun onNotificationPosted(sbn: StatusBarNotification?) {
        super.onNotificationPosted(sbn)
        if (sbn == null) return

        val packageName = sbn.packageName

        if (bankPackages.containsKey(packageName)) {
            val extras = sbn.notification.extras
            val title = extras.getString("android.title") ?: ""
            val text = extras.getCharSequence("android.text")?.toString() ?: ""

            Log.d("ExpenseNotification", "Nhận tin từ ${bankPackages[packageName]}: $title - $text")

            // Kiểm tra dấu hiệu trừ tiền (giao dịch chi tiêu)
            if (text.contains("-") || text.contains("chi") || text.contains("trừ") || text.contains("thanh toan")) {
                val parsed = TransactionParser.parse(text)
                if (parsed.amount > 0) {
                    // Kích hoạt cửa sổ nổi Overlay hiển thị ngay trên màn hình hiện hành
                    val overlay = QuickExpenseOverlay(applicationContext)
                    overlay.showOverlay(parsed.amount, bankPackages[packageName] ?: "Ngân hàng")
                }
            }
        }
    }
}

7. Mã Nguồn Kotlin 3: Cửa Sổ Nổi Nhanh (QuickExpenseOverlay.kt)

Cửa sổ nổi giải quyết triệt để vấn đề “lười gõ lại số tiền”. Khi có thông báo trừ tiền, một Pop-up nhỏ sẽ nổi lên phía trên màn hình để người dùng xác nhận:

package com.yourdomain.expenseapp.utils

import android.content.Context
import android.graphics.PixelFormat
import android.os.Build
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.yourdomain.expenseapp.R

class QuickExpenseOverlay(private val context: Context) {

    private var windowManager: WindowManager? = null
    private var overlayView: View? = null

    fun showOverlay(amount: Long, bankSource: String) {
        windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        overlayView = inflater.inflate(R.layout.popup_quick_expense, null)

        val txtAmount = overlayView?.findViewById<TextView>(R.id.txtAmount)
        val edtContent = overlayView?.findViewById<EditText>(R.id.edtContent)
        val btnSave = overlayView?.findViewById<Button>(R.id.btnSave)
        val btnCancel = overlayView?.findViewById<Button>(R.id.btnCancel)

        txtAmount?.text = String.format("%,d VNĐ (%s)", amount, bankSource)
        edtContent?.hint = "Nhập nội dung: Bát phở, Cà phê..."

        val layoutFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            @Suppress("DEPRECATION")
            WindowManager.LayoutParams.TYPE_PHONE
        }

        val params = WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            layoutFlag,
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
            PixelFormat.TRANSLUCENT
        )

        params.gravity = Gravity.TOP
        params.y = 120

        btnSave?.setOnClickListener {
            val note = edtContent?.text?.toString()?.trim() ?: "Chi tiêu nhanh"
            // Lưu dữ liệu vào Room Database nội bộ...
            closeOverlay()
        }

        btnCancel?.setOnClickListener {
            closeOverlay()
        }

        windowManager?.addView(overlayView, params)
    }

    private fun closeOverlay() {
        if (overlayView != null && windowManager != null) {
            windowManager?.removeView(overlayView)
            overlayView = null
        }
    }
}

8. Thiết Kế Database Room SQLite: Hệ Thống Thẻ Hành Vi (Behavioral Tags)

Để phục vụ bài toán kiếm tiền từ dữ liệu (Data Monetization), cấu trúc cơ sở dữ liệu trên máy điện thoại phải được thiết kế theo 2 bảng riêng biệt:

package com.yourdomain.expenseapp.data

import androidx.room.Entity
import androidx.room.PrimaryKey

// Bảng 1: Lưu lịch sử giao dịch chi tiết của cá nhân (Chỉ lưu ở máy người dùng)
@Entity(tableName = "transactions")
data class TransactionEntity(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val type: String,              // "CHI" hoặc "THU"
    val amount: Long,              // Số tiền chuẩn (50000)
    val rawContent: String,        // Nội dung ("Ăn bát phở")
    val timestamp: Long,           // Thời gian giao dịch (Epoch milliseconds)
    val categoryTag: String        // "DINING_OUT", "COFFEE", "SHOPPING"
)

// Bảng 2: Chấm điểm chân dung người dùng (User Persona Behavioral Scoring)
@Entity(tableName = "user_behavior_tags")
data class BehaviorTagEntity(
    @PrimaryKey val tagName: String, // Ví dụ: "COFFEE_LOVER", "MOM_AND_BABY", "TECH_ENTHUSIAST"
    val score: Int,                  // Tích lũy điểm hành vi (Ví dụ: chi cho bỉm sữa 5 lần → 25 điểm)
    val lastUpdated: Long
)

9. Chiến Lược Big Data Ẩn Danh & Vượt Kiểm Duyệt Google Play

Làm thế nào để vừa kiếm tiền từ thói quen chi tiêu của người dùng, vừa đảm bảo 100% không vi phạm pháp luật bảo vệ quyền riêng tư và chính sách nghiêm ngặt của Google Play Store?

1. Quy Tắc Vàng: Không Bao Giờ Gửi Dữ Liệu Giao Dịch Thô Lên Server

Toàn bộ số tiền chi tiết, số tài khoản ngân hàng và nội dung mua sắm riêng tư được lưu trữ 100% cục bộ trong máy điện thoại. Ứng dụng chỉ định kỳ đồng bộ lên Cloud một gói tin JSON ẩn danh chứa điểm số nhóm sở thích, gắn với Google Advertising ID (AAID):

{
  "advertising_id": "8fa71e62-c110-4b38-9cb5-bb5079a40562",
  "geo_region": "VN-HN",
  "behavior_profile": [
    { "tag_name": "DINING_OUT", "score_level": "HIGH", "time_window": "11:00-13:00" },
    { "tag_name": "COFFEE_LOVER", "score_level": "FREQUENT", "time_window": "07:00-09:00" },
    { "tag_name": "MOM_AND_BABY", "score_level": "MEDIUM", "time_window": "20:00-22:00" }
  ]
}

2. Quy Trình Vượt Qua Vòng Kiểm Duyệt Google Play Khi Dùng Quyền Nhạy Cảm

  1. Minh bạch trong ứng dụng (Prominent In-app Disclosure): Trước khi yêu cầu quyền đọc thông báo, bạn phải tạo một màn hình hướng dẫn trang trọng giải thích: “Ứng dụng chỉ đọc số tiền từ thông báo ngân hàng để tự động ghi chép chi tiêu, cam kết không thu thập mật khẩu hay số tài khoản”. Người dùng bấm “Tôi đồng ý” mới mở cài đặt Android.
  2. Video giải trình thực tế (Demonstration Video): Quay một video màn hình ngắn dưới 3 phút tải lên YouTube (chế độ không công khai) minh họa rõ luồng hoạt động gửi kèm khi submit app lên Google Play Console.
  3. Nút xóa dữ liệu (Account Deletion Requirement): Cung cấp tính năng xóa toàn bộ lịch sử chi tiêu trong màn hình Cài đặt chỉ với một cú nhấp.

10. Câu Hỏi Thường Gặp Về Ứng Dụng Quản Lý Chi Tiêu (FAQ)

1. Nếu người dùng tắt mạng 4G/Wi-Fi thì tính năng nhận diện giọng nói có hoạt động được không?

Nếu thiết bị Android đã cài đặt sẵn gói ngôn ngữ Tiếng Việt Offline của Google (trong Cài đặt → Giọng nói → Nhận dạng ngoại tuyến), bộ nhận diện SpeechRecognizer vẫn hoạt động bình thường mà không cần kết nối mạng Internet. Module regex NLP xử lý từ lóng chạy 100% cục bộ trên CPU máy.

2. Ứng dụng này có thể đưa lên kho ứng dụng Apple App Store cho iPhone được không?

Trên iOS, Apple cấm hoàn toàn quyền đọc thông báo của ứng dụng khác (không có tương đương NotificationListenerService). Vì vậy trên iPhone, bạn phải chuyển đổi sang 2 tính năng thay thế: (1) Nhập liệu giọng nói ASR/NLP (hoạt động tốt như Android); (2) Cho phép người dùng chụp ảnh màn hình biên lai chuyển tiền để app tự dùng công nghệ OCR quét ảnh bóc tách số tiền.

3. Chi phí duy trì hệ thống máy chủ ban đầu cho app này tốn khoảng bao nhiêu tiền?

Do toàn bộ việc nhận diện giọng nói, bóc tách số tiền và lưu trữ giao dịch đều thực hiện ở phía thiết bị (Client-side), server chỉ làm nhiệm vụ tiếp nhận các thẻ hành vi ẩn danh dạng JSON rất nhẹ. Một máy chủ VPS Cloud cơ bản giá khoảng 150.000đ – 300.000đ/tháng có thể phục vụ mượt mà cho 10.000 đến 30.000 người dùng hoạt động hàng ngày.

Trang Bị Thiết Bị Lập Trình & Sách Công Nghệ Android Nâng Cao

Nâng cấp máy trạm lập trình, điện thoại Android test ứng dụng và tài liệu kiến trúc phần mềm:

Nguồn Tài Liệu Trích Xuất & Cơ Sở Kỹ Thuật (Plain Text):
https://developer.android.com/reference/android/service/notification/NotificationListenerService – Tài liệu chính thức Android NotificationListenerService
https://developer.android.com/reference/android/speech/SpeechRecognizer – Kiến trúc nhận diện giọng nói SpeechRecognizer trên nền tảng Android
https://developer.android.com/training/data-storage/room – Hướng dẫn sử dụng cơ sở dữ liệu Room SQLite cục bộ cho Android
https://support.google.com/googleplay/android-developer/answer/9888077 – Chính sách quyền riêng tư và quyền truy cập thông báo của Google Play Store
https://vietqr.net/ – Đặc tả tiêu chuẩn thanh toán mã phản hồi nhanh VietQR (EMVCo) tại Việt Nam
Contents hide
1 Tự Làm App Quản Lý Chi Tiêu Android Bằng QR & Giọng Nói
Back to top button