APK và AAB: Giải thích về định dạng phân phối mới của Android
APK thực sự là gì (Và tại sao nó thống trị Android trong 15 năm)
Trong 15 năm, Android Package Kit—hay APK—là lựa chọn duy nhất. Nó đã là tiêu chuẩn cho các ứng dụng Android kể từ khi nền tảng này ra mắt năm 2008. Một file APK thực chất chỉ là một file nén ZIP với cấu trúc nội bộ rất cụ thể: nó chứa file AndroidManifest.xml đã được biên dịch, mã bytecode DEX (classes.dex), bảng resources.arsc, và các thư mục cho assets, thư viện gốc, và các tài nguyên thô khác. Khi bạn tải một ứng dụng từ một trang web hoặc bắn cho bạn bè qua Bluetooth, bạn đang gửi một file .apk duy nhất chứa mọi thứ cần thiết để chạy trên bất kỳ thiết bị Android nào. Cách tiếp cận "một cho tất cả" đó vừa là điểm mạnh lớn nhất, vừa là yếu điểm chí mạng của APK. Một file APK duy nhất từ Google Play Store phải hỗ trợ mọi thứ, từ một chiếc Samsung Galaxy S25 Ultra với chip ARM 64-bit cho đến một chiếc điện thoại Tecno giá rẻ với chip ARM 32-bit, cộng thêm cả Chromebook trên bộ xử lý x86 và mọi mật độ màn hình có thể tưởng tượng được. Để làm được điều này, các nhà phát triển phải đóng gói mọi phiên bản của từng thư viện gốc, chuỗi dịch, và hình ảnh cho từng mật độ màn hình vào một gói khổng lồ duy nhất. Kết quả? Các ứng dụng như Google Maps sẽ có file APK nặng 100 MB trong khi thiết bị của bạn chỉ cần khoảng 40 MB trong số đó. Phần còn lại chỉ là phần thừa vô dụng—được tải về và lưu trữ, nhưng không bao giờ được sử dụng.
Android App Bundle: Điều gì đã thay đổi vào năm 2018 và tại sao Google bắt buộc sử dụng nó
Google cuối cùng đã giải quyết vấn đề phình to của APK tại sự kiện Google I/O 2018 với Android App Bundle (AAB), và bắt buộc các ứng dụng mới trên Play Store phải sử dụng nó từ tháng 8 năm 2021. Mặc dù có phần mở rộng .aab và cũng là một file nén ZIP, nó không phải là một ứng dụng có thể cài đặt được. Hãy hình dung nó như một công thức và một hộp nguyên liệu, chứ không phải chiếc bánh đã hoàn chỉnh. Một file AAB chứa mã đã biên dịch và tài nguyên trong các module, nhưng máy chủ của Google Play sẽ thực hiện công đoạn lắp ráp cuối cùng. Quá trình này được gọi là Dynamic Delivery. Khi người dùng nhấn 'Cài đặt' trong Play Store, máy chủ của Google sẽ xem xét thiết bị cụ thể của họ—kiến trúc CPU (ABI), mật độ màn hình và cài đặt ngôn ngữ. Sau đó, chúng sẽ xây dựng và cung cấp một bộ các split APK tùy chỉnh chỉ chứa những gì thiết bị đó cần. Một chiếc Pixel 9 chạy Android 15 bằng tiếng Anh có thể nhận được một bản tải xuống 38 MB, trong khi file APK nguyên khối cũ sẽ nặng tới 95 MB. Việc giảm kích thước này không phải là lý thuyết; nó rất đáng kể và có thể đo lường được. Dữ liệu năm 2021 của chính Google cho thấy kích thước trung bình giảm 15% đối với các ứng dụng chuyển sang AAB, một số còn giảm hơn 50%. Đối với một game có các texture atlas khổng lồ được thiết kế cho các định dạng nén GPU khác nhau (như ETC2, ASTC, và S3TC), mức tiết kiệm có thể cực kỳ lớn, dễ dàng loại bỏ hàng trăm megabyte khỏi bản cài đặt cuối cùng trên điện thoại của người dùng.
Cấu trúc bên trong của một file AAB
Nếu bạn mở một file AAB bằng công cụ giải nén ZIP, bạn sẽ thấy ngay nó không phải là một file APK. Ở cấp cao nhất có một file BundleConfig.pb, định nghĩa cấu hình của bundle, một thư mục BUNDLE-METADATA, và ít nhất một thư mục module. Module chính luôn được gọi là `base/`, và bên trong nó trông hơi giống một file APK, với các thư mục `dex/`, `manifest/`, `res/`, `root/`, và `lib/`. Nhưng có một sự khác biệt quan trọng: tài nguyên được lưu trữ ở định dạng proto `resources.pb`, không phải là file nhị phân phẳng `resources.arsc` của APK. Đây là một lý do chính khiến một file AAB không thể được cài đặt trực tiếp. Các module tính năng khác xuất hiện bên cạnh module `base/`, với các tên như `onboarding/` hoặc `ar_features/`. Mỗi module có manifest và tài nguyên riêng và có thể được thiết lập để tải xuống tại thời điểm cài đặt, ngay sau khi cài đặt (fast-follow), hoặc chỉ khi cần thiết. Mô hình theo yêu cầu này là cách một ứng dụng như Google Earth có thể tránh làm nặng máy mọi người dùng với dữ liệu thành phố 3D, chỉ lấy nó thông qua thư viện Play Core khi ai đó thực sự cố gắng xem một thành phố có dữ liệu đó. Thư mục `lib/` bên trong mỗi module là nơi điều kỳ diệu thực sự xảy ra để tiết kiệm dung lượng. Một game đa nền tảng có thể có các thư mục con `arm64-v8a`, `armeabi-v7a`, và `x86_64`, mỗi thư mục chứa đầy các thư viện .so đã được biên dịch. Một file APK nguyên khối sẽ đóng gói tất cả chúng. Với AAB, Dynamic Delivery đảm bảo chỉ có thư mục ABI duy nhất, phù hợp được gửi đi. Đối với một game có 80 MB mã gốc cho mỗi ABI, đó là tiết kiệm ngay lập tức 160 MB trên một chiếc điện thoại 64-bit hiện đại không cần dùng đến các thư viện 32-bit hoặc x86.
APK và AAB: So sánh trực tiếp những điểm quan trọng đối với lập trình viên
Vậy những khác biệt này có ý nghĩa gì trong thực tế đối với các lập trình viên, đội ngũ QA, và người dùng? Hãy cùng phân tích so sánh dựa trên những gì thực sự quan trọng trong công việc hàng ngày của bạn. **Hỗ trợ kênh phân phối:** Google Play yêu cầu AAB cho các ứng dụng mới. Đơn giản là vậy. Tuy nhiên, AAB là một công nghệ chỉ của Google. Các kho ứng dụng Android thay thế như Amazon Appstore, Samsung Galaxy Store, Huawei AppGallery, và F-Droid đều yêu cầu các file APK kiểu cũ. Nếu bạn đang phân phối ứng dụng của mình ngoài Google Play, bạn vẫn phải làm việc với APK. Đây không phải là một chi tiết nhỏ, đặc biệt là ở các thị trường không có Google Play và phân phối chỉ bằng APK là tiêu chuẩn. **Cài đặt trực tiếp:** Bạn không thể sideload một file AAB. Cố gắng cài đặt một file bằng lệnh `adb install app.aab` sẽ chỉ trả về lỗi. Để kiểm thử một file AAB cục bộ, bạn phải sử dụng `bundletool` của Google để tạo ra một bộ APK cục bộ hoặc sử dụng cờ `--local-testing` trong bản build của bạn. Bất kỳ ai đã từng cố gắng nhờ một bên liên quan không rành về kỹ thuật kiểm thử một bản build đều biết rằng việc thêm các bước phụ là một công thức cho sự bực bội. Điều này chắc chắn gây thêm phiền toái cho quy trình QA. **Công cụ build:** Trong Android Studio, bạn tạo một file AAB bằng cách vào Build > Generate Signed Bundle/APK > Android App Bundle, hoặc với tác vụ `./gradlew bundleRelease`. Bạn build một file APK với `./gradlew assembleRelease`. Hầu hết các đội ngũ đều sử dụng cả hai, build APK để kiểm thử nội bộ và AAB cho lần tải lên Play Store cuối cùng. **Kích thước file trên đĩa:** Đây là một điểm dễ gây nhầm lẫn: file AAB của bạn gần như luôn lớn hơn file APK của bạn. Một file APK 60 MB có thể tạo ra một file AAB 80 MB vì AAB chứa tài nguyên cho *tất cả* các cấu hình thiết bị. Việc tiết kiệm dung lượng chỉ xuất hiện trên thiết bị của người dùng sau khi Google Play đã thực hiện 'phép thuật' của mình. **Mô hình bảo mật:** Cả hai định dạng đều được ký, nhưng quy trình khác nhau. Với AAB, bạn phải sử dụng Play App Signing. Điều này có nghĩa là bạn tải lên bundle của mình và Google sẽ ký lại các split APK cuối cùng mà nó tạo ra bằng một khóa do Google quản lý. Mặc dù bạn đăng ký khóa này, cuối cùng Google là người nắm giữ nó, một sự thật khiến một số đội ngũ quan tâm đến bảo mật cảm thấy lo lắng. Với APK, bạn có thể kiểm soát toàn bộ quá trình ký bằng khóa của riêng mình, không cần sự tham gia của Google.
Chuyển đổi giữa APK và AAB: Điều gì có thể và không thể
Đây là lúc những câu trả lời trung thực quan trọng hơn những lời hứa hẹn marketing. Hãy nói thẳng: việc chuyển đổi một file APK hiện có trở lại thành AAB là điều không thể, và bạn nên hết sức hoài nghi về bất kỳ công cụ nào tuyên bố có thể làm điều đó một cách tự động. Vấn đề nằm ở gốc rễ. Một file AAB cần thông tin nguồn ban đầu—các file tài nguyên được sắp xếp gọn gàng theo mật độ màn hình và ngôn ngữ, bảng tài nguyên định dạng proto, cấu trúc module. Tất cả dữ liệu đó đã được biên dịch, làm phẳng và tối ưu hóa đi mất khi một file APK được tạo ra. File `resources.arsc` trong một APK là một khối nhị phân (binary blob); cấu trúc thư mục `res/drawable-hdpi/` ban đầu đã không còn. Cố gắng xây dựng lại điều đó từ một file APK đã biên dịch không phải là chuyển đổi; đó là một quá trình dịch ngược đầy đau đớn, và kết quả gần như luôn không hoàn chỉnh. CocoConvert được xây dựng cho các hoạt động từ APK-sang-APK. Bạn có thể sử dụng nó để đóng gói lại, đổi tên, và hữu ích nhất là trích xuất nội dung của các file APK để kiểm tra. Tải lên một file APK, và bạn có thể lấy ra manifest của nó, xem bảng tài nguyên, hoặc lấy các asset cụ thể. Nhưng điều CocoConvert không thể làm là tạo ra một file AAB hợp lệ, sẵn sàng cho Play Store từ một file APK. Thẳng thắn mà nói, không có công cụ nào có thể làm điều này một cách đáng tin cậy nếu bạn không có mã nguồn gốc của dự án. Nếu bạn đã mất mã nguồn và chỉ còn file APK, lựa chọn tốt nhất của bạn là một công cụ như `apktool`. Nó có thể dịch ngược gói thành mã bytecode smali và cho bạn một phiên bản gần đúng của các tài nguyên, nhưng biến nó trở lại thành một dự án hoàn chỉnh có thể build thành AAB đòi hỏi một lượng lớn công việc thủ công. Điều mà CocoConvert *thực sự* hữu ích là cho các tác vụ thường xuyên xuất hiện trong QA di động và nghiên cứu bảo mật. Bạn có thể chuyển đổi APK thành file ZIP để duyệt nội dung, trích xuất hình ảnh hoặc file âm thanh cụ thể, và thậm chí xử lý hàng loạt cả một thư mục APK để kiểm tra chúng. Đây là những công việc thực tế, đời thường mà chúng tôi có thể giúp bạn.
Vấn đề Sideloading và tại sao APK sẽ không biến mất
Mặc dù Google đang thúc đẩy mạnh mẽ AAB, file APK khiêm tốn sẽ không biến mất. Sự bền bỉ của nó đến từ tất cả các trường hợp sử dụng hoàn toàn nằm ngoài tầm kiểm soát của Google. Sideloading—cài đặt một file APK từ bên ngoài Play Store—là một tính năng cốt lõi của Android, được kích hoạt chỉ bằng cách vào nhanh phần cài đặt của điện thoại (thường là Cài đặt > Ứng dụng > Quyền truy cập đặc biệt > Cài đặt ứng dụng không xác định, mặc dù đường dẫn có thể khác nhau). Và hệ sinh thái sideloading rất lớn. APKMirror lưu trữ các file APK đã được xác minh của các ứng dụng trên Play Store, cho phép người dùng nhận các bản cập nhật trước khi một đợt phát hành theo giai đoạn đến với họ hoặc cài đặt các phiên bản cũ hơn. Các công cụ Quản lý Thiết bị Di động Doanh nghiệp (MDM) từ VMware và Microsoft đẩy các file APK đến hàng nghìn thiết bị của công ty mà không cần chạm vào Play Store. Các cộng đồng mod game sống và thở bằng các file APK đã được chỉnh sửa. Đối với các nhà phát triển ở những khu vực có quyền truy cập Play Store hạn chế, chia sẻ APK là phương thức phân phối chính. Đối với bất kỳ người dùng nào trong số này, AAB đơn giản là không liên quan. Nó là một định dạng sống và chết bên trong khu vườn có tường bao của Google. Ngay khi một ứng dụng cần được chia sẻ, triển khai, hoặc cài đặt bên ngoài hệ sinh thái đó, nó phải là một file APK. Điều này càng trở nên phù hợp hơn với các quy định mới. Đạo luật Thị trường Kỹ thuật số của EU đang buộc cả Apple và Google phải mở cửa cho các kho ứng dụng thay thế. Khi các chợ ứng dụng Android của bên thứ ba trở nên phổ biến ở châu Âu, họ sẽ cần một định dạng chung để nhận ứng dụng. Vì họ không thể tận dụng cơ sở hạ tầng Dynamic Delivery độc quyền của Google, định dạng đó sẽ là APK. Điều này có thể trớ trêu thay lại dẫn đến sự hồi sinh tầm quan trọng của APK ở một số thị trường lớn nhất thế giới, ngay cả khi Google tăng cường áp dụng AAB cho cửa hàng của riêng mình.
Khuyến nghị thực tế dựa trên tình huống của bạn
Vậy, hãy đi thẳng vào vấn đề. Định dạng đúng đắn hoàn toàn phụ thuộc vào việc bạn đang cố gắng làm gì. Dưới đây là một hướng dẫn thẳng thắn, không vòng vo dựa trên vai trò của bạn. **Nếu bạn đang phát hành một ứng dụng mới lên Google Play:** Bạn không có lựa chọn nào khác. Bạn phải gửi một file AAB cho bất kỳ ứng dụng mới nào kể từ tháng 8 năm 2021. Hãy cấu hình Play App Signing trong Play Console (Thiết lập > Tính toàn vẹn của ứng dụng), thiết lập cấu hình ký Gradle của bạn, và chạy `./gradlew bundleRelease`. Hãy chắc chắn kiểm thử nó cục bộ với `bundletool build-apks --bundle=app.aab --output=app.apks --local-testing` theo sau là `bundletool install-apks --apks=app.apks`. **Nếu bạn đang phân phối cho các thiết bị doanh nghiệp qua MDM:** Hãy dùng APK. Build một file với `./gradlew assembleRelease`. Giải pháp MDM của bạn sẽ đẩy trực tiếp file APK đến các thiết bị. Sử dụng AAB ở đây không mang lại giá trị gì mà chỉ tạo thêm phiền phức. **Nếu bạn đang phân phối cho các kho ứng dụng thay thế:** Hãy build APK. Ví dụ, Amazon Appstore có cổng thông tin nhà phát triển riêng để tải lên APK và có logic riêng để nhắm mục tiêu thiết bị. Họ không sử dụng hệ thống của Google. **Nếu bạn là kỹ sư QA đang kiểm thử một bản build:** Sử dụng APK cho các bài smoke test và kiểm thử hồi quy hàng ngày của bạn; chúng nhanh và cài đặt trực tiếp bằng `adb install`. Đối với việc xác thực cuối cùng trước khi phát hành, bạn nên build một file AAB và sử dụng `bundletool` để đảm bảo bạn đang kiểm thử những gì người dùng sẽ thực sự nhận được từ Play Store. **Nếu bạn cần kiểm tra một file APK bạn đã nhận được:** Bạn có thể tải nó lên CocoConvert để nhanh chóng trích xuất nội dung, hoặc sử dụng APK Analyzer của chính Android Studio (Build > Analyze APK). Công cụ analyzer cung cấp một phân tích trực quan tuyệt vời về kích thước file và hoàn hảo để so sánh hai bản build khác nhau để xem điều gì đã thay đổi. Cuối cùng, cuộc tranh luận APK và AAB không phải là về định dạng nào vượt trội hơn về mặt kỹ thuật một cách tách biệt. Vấn đề nằm ở hậu cần (logistics). Lựa chọn đúng đắn được quyết định bởi kênh phân phối và công cụ của bạn. Cả hai định dạng đều sẽ tồn tại, phục vụ những con đường khác nhau trong hệ sinh thái Android rộng lớn.