Tất cả bài viết
mobiledeep linksiOSAndroid

Kiểm thử deep link di động với tunnel localhost

Universal Links trên iOS và App Links trên Android đều yêu cầu một file JSON được phục vụ qua HTTPS ở gốc tên miền của bạn. iOS muốn /.well-known/apple-app-site-association. Android muốn /.well-known/assetlinks.json. localhost không thể phục vụ cái nào qua một hostname mà OS sẽ liên kết với app của bạn. Vậy nên ta tunnel.

Yêu cầu thực tế trên mỗi nền tảng

iOS Universal Links

OS lấy https://your-domain.com/.well-known/apple-app-site-association (hoặc /apple-app-site-association) khi app của bạn được cài. Nó đối chiếu nội dung với entitlement associated domains của app. Việc lấy phải thành công qua HTTPS thật. iOS không tin chứng chỉ tự ký cho mục đích này và không tin localhost.

Android App Links

Android xác minh App Links bằng cách lấy https://your-domain.com/.well-known/assetlinks.json. File phải liệt kê các fingerprint SHA-256 của app. Việc xác minh diễn ra lúc cài và lần khởi chạy đầu tiên. Cùng ràng buộc: HTTPS thật, tên miền thật.

Vì sao localhost không làm trực tiếp được

Ngay cả khi mkcert cho bạn HTTPS đáng tin trong trình duyệt laptop, OS di động không tin CA cục bộ của bạn. Và tên miền trong apple-app-site-association phải khớp với associated-domain trong entitlement của app — đó là một tên miền thật phân giải được qua DNS, không phải localhost.

Một số nhóm né điều này bằng một tên miền staging riêng. Cách đó chạy được, nhưng vòng lặp lặp lại chậm. Một tunnel localhost cho bạn một URL HTTPS thật trên một subdomain thật mà thiết bị di động tiếp cận được không phàn nàn.

Cách đấu nối

  1. Phục vụ apple-app-site-associationassetlinks.json từ máy chủ dev cục bộ tại /.well-known/. Cả hai file. Cả hai route.
  2. Chạy npx portpreview 3000 (hoặc cổng máy chủ dev của bạn dùng).
  3. Ghi lại hostname tunnel — kiểu abc123.portpreview.dev.
  4. Trong entitlement associated domains của app iOS, thêm applinks:abc123.portpreview.dev. Trong intent filter của Android, thêm cùng host đó.
  5. Build và cài app lên thiết bị thật (giả lập có hành vi Universal Link kỳ lạ).
  6. Mở URL từ một app khác — Notes, Mail, một mã QR — và xem nó định tuyến vào app đã cài thay vì trình duyệt.

Điểm vướng khi tunnel cho deep link: hostname tunnel thay đổi giữa các phiên trừ khi bạn có subdomain dành riêng. Mỗi lần xoay vòng nghĩa là build lại app với mục associated-domain mới. Nếu bạn lặp hành vi deep link thường xuyên, hãy lấy một subdomain dành riêng.

content-type quan trọng với apple-app-site-association

iOS mong file không có đuôi và content-type application/json (iOS mới hơn) hoặc application/pkcs7-mime (định dạng cũ, đã ký). Gần như mọi app hiện đại dùng biến thể JSON thuần. Đảm bảo máy chủ dev của bạn trả về đúng content-type, nếu không iOS lặng lẽ từ chối file mà không có lỗi hữu ích.

Kiểm thử từ trình duyệt desktop trước: mở https://your-tunnel.portpreview.dev/.well-known/apple-app-site-association và xác nhận JSON hiển thị và header content-type trong dev tools đúng. Nếu sai, sửa trước khi truy lỗi Universal Link trong giả lập.

Các bẫy gỡ lỗi deep link khác

Lệch entitlement của app

Nếu entitlement associated-domains của bạn ghi applinks:abc.portpreview.dev nhưng apple-app-site-association liệt kê def.portpreview.dev, iOS không lấy. Hostname phải nhất quán.

Universal Link từ bên trong Safari

Chạm một Universal Link bên trong Safari (cùng app mà tab đang mở) đôi khi mở trong Safari thay vì app. Đây là cố ý — iOS ngăn chiêu "mở app mỗi khi người dùng nhấp một liên kết". Hãy kiểm thử từ Notes hoặc Mail.

Android App Links và digital asset links

Android cũng hỗ trợ scheme URL tùy chỉnh (yourapp://path), vốn không cần HTTPS hay assetlinks.json. Chúng dễ kiểm thử hơn nhưng kém an toàn hơn — bất kỳ app nào cũng đăng ký được cùng scheme. Để deep linking chất lượng sản xuất, App Links là câu trả lời.

Luồng kiểm thử di động chúng tôi dùng

Cho một dự án xuất bản cả iOS và Android với deep link:

  1. Khởi động backend phục vụ các file .well-known.
  2. Tunnel nó với npx portpreview 3000.
  3. Khi URL tunnel ổn định cho phiên (hoặc dùng subdomain dành riêng), cập nhật các mục associated-domain của app và build.
  4. QA trên thiết bị vật lý — cả cài mới lẫn cập nhật.
  5. Với combo OAuth-và-deep-link (nhà cung cấp đăng nhập chuyển hướng về app), ghép nó với kiểm thử callback OAuth.

Thiết lập gây phiền ở lần đầu. Sau đó, URL tunnel chỉ là một biến môi trường khác trong scheme Xcode và Gradle.

Để có các mẫu kiểm thử di động rộng hơn, xem kiểm thử di động với tunnel localhost. Tham gia danh sách chờ của PortPreview.

Câu hỏi thường gặp

Tôi có thể kiểm thử iOS Universal Links trên localhost không?
Không trực tiếp. Universal Links yêu cầu iOS lấy apple-app-site-association qua HTTPS thật từ một tên miền thật. localhost không đủ điều kiện. Một tunnel cho bạn một URL HTTPS trên một subdomain tunnel mà iOS sẽ liên kết với app của bạn khi bạn liệt kê nó trong entitlement associated-domains.
apple-app-site-association nên dùng content-type nào?
iOS hiện đại mong application/json. Phiên bản cũ cũng chấp nhận application/pkcs7-mime cho file đã ký. Hầu hết app ngày nay dùng biến thể JSON thuần. Nếu iOS không nhận file của bạn, hãy kiểm tra header content-type từ trình duyệt desktop trước.
Android App Links có cần tunnel để kiểm thử cục bộ không?
Có nếu bạn muốn xác minh App Link đầy đủ (không phải scheme URL tùy chỉnh). Android lấy assetlinks.json qua HTTPS thật từ tên miền trong intent filter của bạn. Một tunnel cung cấp URL HTTPS thật trên một tên miền mà thiết bị có thể xác minh. Scheme tùy chỉnh không cần điều này nhưng kém an toàn hơn.