Deep links cho ứng dụng di động native: routes, token, mở trong app
Tìm hiểu deep link cho ứng dụng di động native: lên kế hoạch routes, xử lý “mở trong app”, và trao mã an toàn cho Kotlin và SwiftUI mà không cần mã routing rối rắm.

Điều mà một deep link nên làm, nói ngắn gọn
Khi ai đó chạm một liên kết trên điện thoại, họ mong đợi một kết quả: liên kết đưa họ đến đúng chỗ, ngay lập tức. Không phải gần đúng. Không phải một trang chính với ô tìm kiếm. Không phải màn hình đăng nhập quên mất lý do họ đến.
Một trải nghiệm deep link tốt trông như sau:
- Nếu app đã được cài, nó mở đúng màn hình mà liên kết ám chỉ.
- Nếu app chưa cài, cú chạm vẫn hữu ích (ví dụ mở trang web fallback hoặc trang cửa hàng ứng dụng và có thể đưa người đó trở lại cùng điểm đến sau khi cài).
- Nếu người dùng phải đăng nhập, họ chỉ đăng nhập một lần và đến màn hình định trước, không phải màn hình khởi động mặc định của app.
- Nếu liên kết mang một hành động (chấp nhận invite, xem đơn hàng, xác nhận email), hành động đó rõ ràng và an toàn.
Hầu hết sự thất vọng đến từ các liên kết “hơi hoạt động” nhưng phá vỡ luồng. Người dùng thấy màn hình sai, mất việc họ đang làm, hoặc bị kẹt trong vòng lặp: chạm liên kết, đăng nhập, về dashboard, chạm lại, đăng nhập lại. Chỉ một bước thừa cũng có thể khiến người dùng bỏ cuộc, đặc biệt với hành động một lần như invite hay đặt lại mật khẩu.
Trước khi viết bất kỳ mã Kotlin hay SwiftUI nào, hãy quyết định liên kết có ý nghĩa gì. Màn hình nào có thể được mở từ bên ngoài? Điều gì thay đổi nếu app đóng so với đang chạy? Điều gì nên xảy ra khi người dùng chưa đăng nhập?
Việc lên kế hoạch ngăn được hầu hết cơn đau sau này: routes rõ ràng, hành vi “mở trong app” dự đoán được, và cách an toàn để trao mã một lần mà không đặt bí mật trực tiếp trong URL.
Các loại deep link và nơi “mở trong app” thường sai
Không phải mọi “liên kết mở app” đều giống nhau. Đối xử chúng như hoán đổi được và bạn sẽ gặp các lỗi kinh điển: liên kết mở nhầm nơi, mở trình duyệt thay vì app, hoặc chỉ hoạt động trên một nền tảng.
Ba nhóm phổ biến:
- Custom schemes (ví dụ scheme riêng của app như myapp:). Dễ cấu hình, nhưng nhiều app và trình duyệt xử lý chúng thận trọng.
- Universal Links (iOS) và App Links (Android). Dùng URL web bình thường và có thể mở app khi đã cài, hoặc fallback về website khi chưa.
- Liên kết trong trình duyệt nhúng của app. Liên kết mở bên trong app email hoặc messenger thường xử lý khác so với Safari hay Chrome.
“Mở trong app” có thể nghĩa khác nhau tùy nơi chạm. Liên kết chạm trong Safari có thể nhảy thẳng vào app. Cùng liên kết chạm trong email hoặc messenger có thể mở web view nhúng trước, và người dùng phải bấm thêm nút “mở” (hoặc không bao giờ thấy nút đó). Trên Android, Chrome có thể tôn trọng App Links còn trình duyệt nhúng của app xã hội có thể bỏ qua.
Cold start so với app đã chạy là cái bẫy tiếp theo.
- Cold start: OS khởi chạy app, app khởi tạo, và chỉ sau đó bạn nhận deep link. Nếu flow khởi động của bạn hiển thị splash, kiểm tra auth, hoặc tải cấu hình từ xa, liên kết có thể bị mất trừ khi bạn lưu nó và phát lại sau khi app sẵn sàng.
- Đang chạy: bạn nhận liên kết khi người dùng đang trong phiên. Ngăn xếp điều hướng đã tồn tại, nên cùng điểm đến có thể cần xử lý khác (push màn hình hay reset stack).
Một ví dụ đơn giản: một liên kết invite chạm từ Telegram thường mở trong trình duyệt nhúng trước. Nếu app bạn giả định OS luôn hand off trực tiếp, người dùng sẽ thấy trang web và cho rằng liên kết bị hỏng. Lập kế hoạch cho những môi trường này ngay từ đầu và bạn sẽ viết ít đoạn glue đặc thù nền tảng hơn sau này.
Lên kế hoạch routes trước khi triển khai
Phần lớn lỗi deep link không phải là lỗi Kotlin hay SwiftUI. Chúng là lỗi kế hoạch. Liên kết không ánh xạ rõ ràng đến một màn hình, hoặc mang quá nhiều tùy chọn “có thể”.
Bắt đầu với một mẫu route nhất quán phù hợp cách người dùng nghĩ về app: danh sách, chi tiết, cài đặt, thanh toán, invite. Giữ nó dễ đọc và ổn định, vì bạn sẽ dùng lại trong email, QR code và trang web.
Một bộ route đơn giản có thể gồm:
- Home
- Danh sách đơn hàng và Chi tiết đơn hàng (orderId)
- Cài đặt tài khoản
- Chấp nhận invite (inviteId)
- Tìm kiếm (query, tab)
Rồi xác định các tham số:
- Dùng ID cho đối tượng đơn lẻ (orderId).
- Dùng tham số tùy chọn cho trạng thái UI (tab, filter).
- Quyết định mặc định để mọi liên kết có một đích tốt nhất.
Cũng quyết định chuyện gì xảy ra khi liên kết sai: dữ liệu thiếu, ID không hợp lệ, hoặc nội dung người dùng không truy cập được. Mặc định an toàn nhất là mở màn hình ổn định gần nhất (như danh sách) và hiển thị thông báo ngắn. Tránh để người dùng vào màn hình trắng hoặc màn hình đăng nhập không có ngữ cảnh.
Cuối cùng, lên kế hoạch theo nguồn. QR code thường cần route ngắn, mở nhanh và chịu được kết nối kém. Liên kết email có thể dài hơn và chứa thêm ngữ cảnh. Liên kết trang web nên xuống cấp duyên dáng: nếu app chưa cài, người dùng vẫn đến một nơi giải thích bước tiếp theo.
Nếu bạn dùng phương pháp do backend điều khiển (ví dụ tạo endpoint API và màn hình với nền tảng như AppMaster), kế hoạch routes này trở thành hợp đồng chung: app biết đi đâu, backend biết ID và trạng thái nào hợp lệ.
Trao tay token an toàn mà không đặt bí mật trong URL
Người ta thường coi deep link như phong bì an toàn. Không phải vậy. Bất cứ thứ gì trong URL có thể vào lịch sử trình duyệt, ảnh chụp màn hình, bản xem trước chia sẻ, log phân tích, hoặc bị sao chép vào chat.
Tránh đặt bí mật trong liên kết. Bao gồm token truy cập dài hạn, refresh token, mật khẩu, dữ liệu cá nhân, hoặc bất cứ thứ gì cho phép ai đó hành động thay người dùng nếu liên kết bị chuyển tiếp.
Mẫu an toàn hơn là mã dùng một lần, thời hạn ngắn. Liên kết chỉ mang mã đó, và app đổi nó lấy phiên thực sự sau khi mở. Nếu ai đó lấy liên kết, mã sẽ vô dụng sau một hoặc hai phút, hoặc sau lần đổi đầu tiên.
Một luồng trao tay đơn giản:
- Liên kết chứa mã một lần, không phải session token.
- App mở và gọi backend để đổi mã.
- Backend kiểm tra hạn dùng, đảm bảo chưa dùng, rồi đánh dấu là đã dùng.
- Backend trả về session đã xác thực cho app.
- App xóa mã khỏi bộ nhớ sau khi đổi.
Ngay cả sau khi đổi thành công, hãy xác nhận danh tính trong app trước khi làm việc nhạy cảm. Nếu liên kết dùng để duyệt thanh toán, đổi email hoặc xuất dữ liệu, yêu cầu kiểm tra nhanh như sinh trắc học hoặc đăng nhập lại.
Lưu session nhận được một cách an toàn. Trên iOS, thường dùng Keychain. Trên Android, dùng lưu trữ có hỗ trợ Keystore. Chỉ lưu những gì cần thiết, và xóa khi logout, xóa tài khoản, hoặc khi phát hiện tái sử dụng đáng ngờ.
Một ví dụ cụ thể: bạn gửi liên kết invite vào workspace. Liên kết mang mã một lần hết hạn sau 10 phút. App đổi mã, rồi hiển thị màn hình nêu rõ điều gì sẽ xảy ra tiếp theo (vào workspace nào). Chỉ sau khi người dùng xác nhận, app mới hoàn tất việc tham gia.
Nếu bạn xây dựng với AppMaster, điều này áp dụng rõ ràng vào một endpoint đổi mã trả session, trong khi UI di động xử lý bước xác nhận trước khi thực hiện hành động quan trọng.
Xác thực và “tiếp tục nơi bạn đã dừng lại”
Deep link thường trỏ đến màn hình chứa dữ liệu riêng tư. Bắt đầu bằng cách quyết định cái gì có thể mở cho bất kỳ ai (public) và cái gì yêu cầu phiên đăng nhập (protected). Quyết định này tránh hầu hết các bất ngờ “làm việc trong test”.
Quy tắc đơn giản: deep link tới trạng thái landing an toàn trước, rồi mới điều hướng đến màn hình được bảo vệ sau khi xác nhận người dùng đã xác thực.
Quyết định public vs protected
Xem deep link như có thể bị chuyển tiếp cho người không đúng.
- Public: trang marketing, bài trợ giúp, bắt đầu đặt lại mật khẩu, bắt đầu chấp nhận invite (chưa hiển thị dữ liệu)
- Protected: chi tiết đơn hàng, tin nhắn, cài đặt tài khoản, màn hình admin
- Hỗn hợp: màn hình xem trước được, nhưng chỉ hiển thị placeholder không nhạy cảm cho đến khi đăng nhập
“Tiếp tục sau khi đăng nhập” để trả về đúng chỗ
Cách đáng tin là: phân tích liên kết, lưu đích dự định, rồi route theo trạng thái auth.
Ví dụ: người dùng chạm liên kết “mở trong app” đến một ticket hỗ trợ trong khi chưa đăng nhập. App nên mở một màn hình trung lập, yêu cầu đăng nhập, rồi tự động đưa họ tới ticket đó sau khi đăng nhập.
Để giữ độ tin cậy, lưu một “return target” nhỏ cục bộ (tên route kèm ticket ID) với thời hạn ngắn. Sau khi đăng nhập xong, đọc nó một lần, điều hướng, rồi xóa. Nếu đăng nhập thất bại hoặc mục tiêu hết hạn, fallback về màn hình Home an toàn.
Xử lý ngoại lệ với tôn trọng:
- Phiên hết hạn: hiển thị thông báo ngắn, yêu cầu xác thực lại, rồi tiếp tục.
- Quyền bị thu hồi: mở vỏ màn hình đích, rồi báo “Bạn không còn quyền truy cập” và gợi ý bước tiếp theo an toàn.
Cũng tránh hiển thị dữ liệu nhạy cảm trong bản xem trước màn hình khóa, danh sách app switcher, hoặc thông báo. Giữ màn hình nhạy cảm trống cho đến khi dữ liệu tải và phiên được xác minh.
Cách tiếp cận routing tránh mớ navigation rối
Deep link trở nên rối khi mỗi màn hình tự phân tích URL theo cách riêng. Điều đó gieo rắc các quyết định nhỏ (tham số nào là tùy chọn, bắt buộc gì, hợp lệ ra sao) khắp app, và sẽ rất khó sửa an toàn.
Xem routing như hệ thống ống chung. Giữ một bảng route và một bộ phân tích chung, để UI nhận vào input sạch.
Dùng một bảng route chung
Cho iOS và Android đồng ý về một danh sách routes dễ đọc. Nghĩ về nó như hợp đồng.
Mỗi route ánh xạ tới:
- một màn hình, và
- một mô hình input nhỏ.
Ví dụ, “Chi tiết đơn hàng” ánh xạ tới màn hình Order với input như OrderRouteInput(id). Nếu route cần giá trị thêm (như ref source), chúng thuộc về input model đó, không rải rác trong code view.
Tập trung parsing và validation
Giữ phần parsing, decode và validation ở một nơi. UI không nên hỏi “token này có không?” hay “ID này hợp lệ không?” Nó nên nhận được hoặc một input route hợp lệ hoặc một trạng thái lỗi rõ ràng.
Một flow thực tế:
- Nhận URL (chạm, quét, share sheet)
- Parse thành route đã biết
- Validate các trường bắt buộc và định dạng cho phép
- Tạo mục tiêu màn hình kèm input model
- Điều hướng qua một entry point duy nhất
Thêm một màn hình fallback cho “liên kết không xác định”. Làm nó hữu dụng, không là ngõ cụt: hiển thị những gì không mở được, giải thích ngắn gọn bằng ngôn ngữ dễ hiểu, và gợi ý hành động tiếp theo như về Home, tìm kiếm, hoặc đăng nhập.
Bước theo bước: thiết kế deep link và hành vi “mở trong app”
Deep link tốt khiến trải nghiệm nhàm chán ở điểm tốt: người ta chạm và đến đúng màn hình, dù app đã cài hay chưa.
Bước 1: chọn entry point quan trọng
Liệt kê 10 loại liên kết đầu tiên người dùng thực sự dùng: invites, đặt lại mật khẩu, biên lai đơn hàng, link “xem ticket”, link khuyến mãi. Giữ số lượng nhỏ có chủ ý.
Bước 2: viết pattern như hợp đồng
Với mỗi entry point, định nghĩa một mẫu chuẩn và dữ liệu tối thiểu cần để mở đúng màn hình. Ưu tiên ID ổn định hơn tên. Quyết định tham số nào bắt buộc, nào tùy chọn.
Quy tắc hữu ích:
- Một mục đích cho mỗi route (invite, reset, receipt).
- Tham số bắt buộc luôn có; tham số tùy chọn có mặc định an toàn.
- Dùng cùng pattern trên iOS (SwiftUI) và Android (Kotlin).
- Nếu dự kiến thay đổi, dự phòng tiền tố version đơn giản (ví dụ v1).
- Định nghĩa hành vi khi thiếu tham số (hiển thị màn hình lỗi, không phải trang trống).
Bước 3: quyết định hành vi đăng nhập và đích sau đăng nhập
Ghi rõ, theo từng loại liên kết, liệu có yêu cầu đăng nhập hay không. Nếu có, ghi nhớ đích và tiếp tục sau khi đăng nhập.
Ví dụ: liên kết biên lai có thể hiển thị xem trước mà không cần đăng nhập, nhưng bấm “Tải hoá đơn” có thể yêu cầu đăng nhập và phải trả người dùng về đúng biên lai đó.
Bước 4: đặt quy tắc trao tay token (không để bí mật trong URL)
Nếu liên kết cần token một lần (chấp nhận invite, reset, sign-in magic), định nghĩa thời hạn và cách sử dụng. Cách thực tế: URL mang mã một lần ngắn hạn, và app đổi nó với backend để lấy session thực.
Bước 5: test ba trạng thái thực tế
Deep link hỏng ở rìa. Test mỗi loại liên kết trong:
- Cold start (app đóng)
- Warm start (app trong bộ nhớ)
- Chưa cài app (liên kết vẫn đưa tới chỗ có ý nghĩa)
Nếu bạn giữ routes, kiểm tra auth và luật đổi mã ở một chỗ, bạn tránh việc rải rác logic routing khắp mã Kotlin và SwiftUI.
Lỗi phổ biến làm hỏng deep link (và cách tránh)
Deep link thường hỏng vì những lý do tẻ nhạt: một giả định nhỏ, một màn hình đổi tên, hoặc một “mã tạm thời” cuối cùng nằm ở khắp nơi.
Những lỗi thường gặp và cách sửa
-
Đưa access token vào URL (và rò rỉ vào log). Query string bị sao chép, chia sẻ, lưu trong lịch sử và bị bắt bởi analytics và crash logs. Sửa: chỉ đưa mã một lần ngắn vào liên kết, đổi mã trong app và hết hạn nhanh.
-
Giả định app đã cài (không có fallback). Nếu liên kết mở ra trang lỗi hoặc không làm gì, người dùng bỏ cuộc. Sửa: cung cấp trang web fallback giải thích điều sẽ xảy ra và đường dẫn cài đặt. Một trang “Mở app để tiếp tục” đơn giản vẫn tốt hơn im lặng.
-
Không xử lý nhiều tài khoản trên một thiết bị. Mở màn hình đúng cho người dùng sai còn tệ hơn liên kết hỏng. Sửa: khi nhận link, kiểm tra tài khoản đang hoạt động, yêu cầu xác nhận hoặc chuyển tài khoản, rồi tiếp tục. Nếu hành động cần workspace cụ thể, đính kèm identifier workspace (không phải bí mật) và validate.
-
Làm hỏng liên kết khi đổi tên màn hình hoặc route. Nếu route liên kết với tên UI, liên kết cũ chết ngay khi bạn đổi tên tab. Sửa: thiết kế routes ổn định, theo intent (invite, ticket, order) và giữ tương thích ngược.
-
Không có khả năng truy nguyên khi lỗi. Nếu không thể phát lại chuyện gì đã xảy ra, support chỉ đoán mò. Sửa: đưa một request ID không nhạy cảm vào liên kết, log nó trên server và trong app, và hiển thị mã lỗi kèm ID đó.
Một kiểm tra thực tế nhanh: tưởng tượng liên kết invite gửi trong chat nhóm. Ai đó mở trên điện thoại công ty với hai tài khoản, app chưa cài trên tablet, và liên kết bị chuyển tiếp cho đồng nghiệp. Nếu liên kết chỉ chứa mã invite, có fallback, yêu cầu chọn tài khoản phù hợp, và log request ID, thì liên kết đó có thể thành công trong mọi tình huống mà không lộ bí mật.
Ví dụ: liên kết invite mở đúng màn hình mọi lần
Invite là ví dụ kinh điển: người quản lý gửi đồng nghiệp một link trong messenger, người nhận mong đợi một chạm để đến màn hình invite, không phải trang chủ chung.
Kịch bản: một quản lý mời nhân viên mới vào workspace “Support Team”. Người được mời chạm invite trong Telegram.
Nếu app đã cài, hệ thống nên mở app và truyền chi tiết invite. Nếu chưa cài, người dùng nên tới một trang web giải thích invite và đề xuất cài đặt. Sau khi cài và mở lần đầu, app vẫn phải hoàn tất luồng invite để người dùng không phải đi tìm lại liên kết.
Trong app, luồng giống nhau trên Kotlin và SwiftUI:
- Đọc mã invite từ liên kết nhận vào.
- Kiểm tra người dùng đã đăng nhập chưa.
- Xác thực invite với backend, rồi route tới màn hình đúng.
Xác thực là mấu chốt. Liên kết không nên chứa bí mật như session token dài hạn. Nó chỉ nên mang mã invite một lần mà server kiểm tra.
Trải nghiệm người dùng nên dự đoán được:
- Chưa đăng nhập: thấy màn hình đăng nhập, sau đó quay lại chấp nhận invite.
- Đã đăng nhập: thấy một màn hình xác nhận “Tham gia workspace”, rồi vào workspace đúng.
Nếu invite hết hạn hoặc đã được dùng, đừng ném người dùng vào trang lỗi trống. Hiển thị thông báo rõ ràng và bước tiếp theo: yêu cầu invite mới, đổi tài khoản, hoặc liên hệ admin. “Invite này đã được chấp nhận” tốt hơn “Token không hợp lệ.”
Checklist nhanh và bước tiếp theo
Deep link chỉ thực sự xong khi hành vi giống nhau ở mọi nơi: cold start, warm start, và khi người dùng đã đăng nhập.
Checklist nhanh
Trước khi phát hành, test trên thiết bị thật và phiên bản OS:
- Liên kết mở đúng màn hình khi cold start và warm start.
- Không có dữ liệu nhạy cảm trong URL. Nếu phải truyền token, hãy làm nó ngắn hạn và ưu tiên một lần.
- Liên kết không xác định, hết hạn hoặc đã dùng rơi về màn hình rõ ràng với thông báo và bước an toàn tiếp theo.
- Hoạt động từ app email, trình duyệt, máy quét QR và preview của messenger (một số sẽ mở trước liên kết).
- Logging cho biết điều gì đã xảy ra (nhận liên kết, parse route, cần auth, lý do thành công hoặc thất bại).
Một cách đơn giản để kiểm tra là chọn vài liên kết bắt buộc hoạt động (invite, reset mật khẩu, chi tiết đơn hàng, ticket hỗ trợ, khuyến mãi) và chạy chúng qua cùng flow test: chạm từ email, chạm từ chat, quét QR, mở sau khi cài lại.
Bước tiếp theo (giữ dễ bảo trì)
Nếu deep link bắt đầu lan rộng khắp các màn hình, coi routing và auth là hệ thống chung, không phải mã từng màn hình. Tập trung parsing route vào một chỗ, và làm cho mọi đích nhận parameter sạch (không phải URL thô). Làm tương tự với auth: một cổng quyết định “tiếp tục ngay” hay “đăng nhập trước, rồi tiếp tục”.
Nếu muốn giảm mã glue thủ công, việc xây backend, auth và app mobile cùng nhau sẽ giúp. AppMaster (appmaster.io) là nền tảng no-code tạo backend và app native sẵn sàng production, giúp giữ tên route và endpoint đổi mã một lần đồng bộ khi yêu cầu thay đổi.
Nếu chỉ làm một việc trong tuần tới: viết xuống canonical routes và hành vi fallback chính xác cho từng trường hợp lỗi, rồi triển khai những quy tắc đó trong một lớp routing duy nhất.
Câu hỏi thường gặp
Một deep link nên mở đúng màn hình mà liên kết ám chỉ, không phải một trang chủ chung hay dashboard. Nếu app chưa được cài, liên kết vẫn nên hữu ích bằng cách dẫn tới nơi hợp lý và hướng dẫn người dùng quay lại cùng điểm đến sau khi cài đặt.
Universal Links (iOS) và App Links (Android) dùng URL web bình thường và có thể mở app khi đã cài, đồng thời có fallback mượt mà khi chưa có. Custom scheme dễ cấu hình hơn nhưng có thể bị chặn hoặc xử lý không nhất quán bởi trình duyệt và app khác, nên coi đó là tùy chọn phụ.
Nhiều app email và messenger mở liên kết trong trình duyệt nhúng của chính họ, và những trình duyệt này có thể không hand off sang hệ điều hành giống như Safari hay Chrome. Hãy chuẩn bị cho bước phụ bằng cách làm cho trang fallback web rõ ràng và xử lý trường hợp người dùng thấy web trước rồi mới vào app.
Trên cold start, app có thể hiện splash, chạy kiểm tra khởi tạo hoặc tải config trước khi sẵn sàng điều hướng. Cách đáng tin là lưu ngay mục tiêu liên kết khi nhận, hoàn tất khởi tạo, rồi “phát lại” điều hướng khi app sẵn sàng.
Không đưa access token dài hạn, refresh token, mật khẩu hay dữ liệu cá nhân vào URL vì URL có thể bị ghi lại, chia sẻ và cache. Dùng mã một lần có thời hạn ngắn trong liên kết và đổi mã này với backend sau khi app mở.
Phân tích liên kết, lưu mục tiêu dự định, rồi điều hướng theo trạng thái xác thực: đăng nhập xảy ra một lần và người dùng được đưa về đúng màn hình. Giữ “return target” nhỏ, có thời hạn, và xóa sau khi dùng.
Xem routes như một hợp đồng chung và tập trung parsing cùng validation ở một chỗ, rồi truyền các input sạch cho màn hình thay vì URL thô. Cách này tránh việc mỗi màn hình tự đặt ra quy tắc riêng về tham số tùy chọn, ID thiếu hay lỗi.
Khi nhận liên kết, kiểm tra tài khoản đang hoạt động và liệu nó phù hợp với workspace/tenant mà liên kết ám chỉ hay không; nếu không, yêu cầu người dùng xác nhận hoặc chuyển tài khoản trước khi hiển thị nội dung riêng tư. Một bước xác nhận ngắn còn tốt hơn là mở màn hình đúng nhưng dưới nhầm tài khoản.
Mặc định mở màn hình ổn định gần nhất, ví dụ trang danh sách, và hiển thị thông báo ngắn giải thích phần nào không thể mở được. Tránh màn hình trắng, lỗi im lặng, hoặc đưa người dùng tới trang đăng nhập mà không có ngữ cảnh.
Kiểm tra mỗi loại liên kết quan trọng ở ba trạng thái: app đóng, app đang chạy, và app chưa cài; thực hiện từ nguồn thực như email, chat và máy quét QR. Nếu bạn xây dựng với AppMaster (appmaster.io), bạn có thể giữ tên routes và endpoint đổi mã một lần đồng bộ giữa backend và app native khi yêu cầu thay đổi, giúp giảm lượng glue code cần duy trì.


