AndroidManifest.xml là tệp cấu hình bắt buộc cho mỗi ứng dụng Android mô tả các thành phần, quyền và siêu dữ liệu của nó. Hệ thống Android đọc tệp này khi cài đặt và khởi chạy mỗi ứng dụng. Theo Android Developers, 2025, nếu không có manifest chính xác, ứng dụng sẽ không được cài đặt trên thiết bị. AndroidManifest.xml đăng ký Activity, Service, BroadcastReceiver và ContentProvider cho hệ điều hành.
Điểm chính
AndroidManifest.xml là tệp cấu hình gốc ở định dạng XML mà mọi dự án Android phải có trong thư mục app/src/main. Hệ thống Android phân tích nó trước khi chạy bất kỳ mã ứng dụng nào — trong quá trình phân tích APK khi cài đặt. Nếu manifest có lỗi cú pháp hoặc thiếu khai báo bắt buộc, quá trình cài đặt sẽ bị gián đoạn với thông báo lỗi.
Tệp này chứa khai báo đầy đủ của ứng dụng: danh sách tất cả các thành phần (Activity, Service, BroadcastReceiver, ContentProvider), quyền được yêu cầu, phiên bản SDK tối thiểu, yêu cầu phần cứng và cấu hình chủ đề và kiểu. Mọi thành phần có thể được gọi bởi hệ thống hoặc các ứng dụng khác phải được khai báo rõ ràng trong manifest. Đây là yêu cầu bảo mật: nếu không có khai báo rõ ràng, thành phần sẽ không khả dụng để gọi.
Nếu không có manifest được cấu hình đúng, ứng dụng không thể được cài đặt qua Google Play hoặc sideloading. Hệ thống kiểm tra manifest trong quá trình phân tích APK và từ chối cài đặt nếu có lỗi. Google Play cũng quét manifest để tìm cấu hình không an toàn: nếu exported=true trên thành phần không có intent-filter, một cảnh báo sẽ được đưa ra; và nếu thiếu các quyền bắt buộc cho targetSdk 34+, việc xuất bản sẽ bị chặn. Do đó, hiểu cấu trúc manifest là kỹ năng bắt buộc cho các nhà phát triển Android.
Mỗi thành phần ứng dụng Android phải được đăng ký rõ ràng trong manifest. Đây là yêu cầu bắt buộc của nền tảng cho tất cả bốn loại thành phần. Nếu không đăng ký, thành phần không thể được tạo bởi hệ thống và việc cố gắng khởi chạy nó sẽ dẫn đến ActivityNotFoundException hoặc ngoại lệ tương tự. Các thành phần được đăng ký trong thẻ application theo thứ tự không ảnh hưởng đến hoạt động của chúng.
Thẻ activity đăng ký một màn hình ứng dụng. Thuộc tính exported xác định liệu các ứng dụng khác có thể khởi chạy Activity này hay không. Từ Android 12, việc thiếu exported khi có intent-filter sẽ gây ra lỗi biên dịch — đây là yêu cầu bảo mật. Điểm vào được đặt qua intent-filter với action MAIN và category LAUNCHER. Mỗi Activity phải có android:name duy nhất tương ứng với tên lớp đầy đủ hoặc tương đối.
<activity
android:name=".MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Thẻ service định nghĩa một dịch vụ nền. Từ Android 8, các dịch vụ nền có những hạn chế nghiêm ngặt: foreground service yêu cầu thông báo bắt buộc có biểu tượng mà người dùng nhìn thấy, và bound service chỉ tồn tại khi có một client liên kết với nó. Các dịch vụ chạy nền mà không có thông báo sẽ bị hệ thống tự động kết thúc trong vòng vài phút sau khi ứng dụng chuyển sang nền. Đối với các tác vụ dài, hãy sử dụng WorkManager thay vì Service.
<service
android:name=".SyncService"
android:exported="false"
android:foregroundServiceType="dataSync" />
Thẻ receiver khai báo một bộ thu nhận các thông điệp broadcast hệ thống hoặc tùy chỉnh. Từ Android 8, hầu hết các broadcast ngầm định không còn được gửi đến các bộ thu được khai báo tĩnh trong manifest. Thay vào đó, nên đăng ký các bộ thu động qua Context.registerReceiver trong mã. Các ngoại lệ bao gồm một số broadcast hệ thống như BOOT_COMPLETED, vẫn yêu cầu đăng ký tĩnh trong manifest.
<receiver
android:name=".ConnectivityReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Mỗi quyền nguy hiểm trong Android yêu cầu khai báo trong manifest qua thẻ uses-permission. Từ Android 6, các quyền nguy hiểm được yêu cầu trong thời gian chạy qua hộp thoại với người dùng, nhưng khai báo trong manifest vẫn là bắt buộc. Nếu không có nó, phương thức requestPermissions sẽ ném SecurityException. Các quyền cấp độ bình thường như INTERNET và ACCESS_NETWORK_STATE được cấp tự động khi cài đặt.
| Quyền | Mục đích |
|---|---|
| CAMERA | Truy cập máy ảnh thiết bị để chụp ảnh và quay video |
| ACCESS_FINE_LOCATION | Định vị chính xác qua GPS và mạng |
| RECORD_AUDIO | Ghi âm từ micro của thiết bị |
| READ_CONTACTS | Đọc danh bạ từ sổ điện thoại |
| POST_NOTIFICATIONS | Gửi thông báo trên Android 13+ |
Thẻ uses-permission-sdk-23 chỉ định các quyền cần thiết trên Android 6.0+. Điều này cho phép duy trì tương thích với các phiên bản cũ hơn mà không yêu cầu các quyền không tồn tại. Ví dụ, POST_NOTIFICATIONS chỉ khả dụng trên Android 13+, vì vậy nó phải được chỉ định qua uses-permission-sdk-33 để tránh lỗi quyền không xác định trên các thiết bị cũ. Thuộc tính maxSdkVersion trong uses-permission cho phép tự động thu hồi các quyền không cần thiết khi cập nhật ứng dụng trên các phiên bản Android mới hơn.
Các quyền cấp độ bình thường (INTERNET, ACCESS_NETWORK_STATE) được cấp tự động khi cài đặt và không yêu cầu yêu cầu trong thời gian chạy. Chúng cũng được khai báo qua uses-permission nhưng không hiển thị cho người dùng trong hộp thoại. Để kiểm soát quyền truy cập vào các thành phần ứng dụng từ các ứng dụng khác, cơ chế thành phần được bảo vệ bằng quyền được sử dụng: bạn có thể chỉ định một quyền tùy chỉnh ở cấp Activity hoặc Service, quyền này sẽ được hệ thống kiểm tra khi thành phần được gọi từ bên ngoài. Điều này cung cấp một lớp bảo mật bổ sung cho giao tiếp giữa các tiến trình.
Thẻ intent-filter trong manifest khai báo intent ngầm nào mà một thành phần có thể xử lý. Đây là cơ chế mà Android kết nối các hành động hệ thống hoặc tùy chỉnh với ứng dụng. Một intent filter bao gồm ba yếu tố: action, category và data. Cả ba có thể được kết hợp để mô tả chính xác intent nào mà thành phần nên nhận. Hệ thống chọn thành phần thích hợp dựa trên bộ lọc cụ thể nhất.
<activity android:name=".DeepLinkActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="itsectr.com"
android:pathPrefix="/app" />
</intent-filter>
</activity>
Thuộc tính autoVerify bật xác minh Android App Links: hệ thống liên hệ với máy chủ để xác nhận quyền sở hữu tên miền. Nếu không xác minh, các deep link hoạt động qua hộp thoại chọn tiêu chuẩn nơi người dùng chọn ứng dụng để mở liên kết. Sau khi xác minh thành công, các liên kết mở trực tiếp trong ứng dụng mà không cần hộp thoại. Google Search Console cũng sử dụng autoVerify để lập chỉ mục các deep link và hiển thị chúng trong kết quả tìm kiếm.
Các bộ lọc với action.VIEW và các category DEFAULT và BROWSABLE xử lý các liên kết từ trình duyệt, email và các ứng dụng khác. Đây là cơ chế chính để triển khai deep link trong Android. Để hỗ trợ lược đồ URL tùy chỉnh như myapp://, chỉ cần chỉ định scheme mà không có host. Tuy nhiên, Google khuyến nghị sử dụng deep link HTTPS thay vì lược đồ tùy chỉnh vì chúng an toàn hơn và không yêu cầu quyền bổ sung. Các lược đồ tùy chỉnh có thể bị chặn bởi bất kỳ ứng dụng nào đăng ký cùng một lược đồ.
Thẻ gốc manifest chứa các thuộc tính gói, phiên bản và SDK. Thẻ application lưu trữ các cài đặt toàn cục: chủ đề, biểu tượng, nhãn và cờ gỡ lỗi. Các thuộc tính manifest xác định việc quản lý phiên bản ở cấp gói, trong khi các thuộc tính application xác định giao diện và hành vi tổng thể của ứng dụng. Các giá trị có thể là tham chiếu tài nguyên qua cú pháp @ hoặc chuỗi ký tự.
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itsectr.myapp"
<uses-sdk
android:minSdkVersion="24"
android:targetSdkVersion="34" />
<application
android:label="MyApp"
android:icon="@mipmap/ic_launcher"
android:theme="@style/Theme.MyApp"
android:supportsRtl="true"
android:allowBackup="true">
<!-- Các thành phần ứng dụng -->
</application>
</manifest>
Thẻ meta-data bên trong application cho phép lưu trữ các cặp khóa-giá trị tùy ý. Điều này thuận tiện cho việc cấu hình các thư viện bên thứ ba: khóa API, URL điểm cuối và cờ tính năng. Dữ liệu từ meta-data có thể truy cập qua PackageManager.getApplicationInfo().metaData trong thời gian chạy. Ví dụ, Firebase và Google Maps sử dụng meta-data để truyền khóa truy cập mà không cần mã cứng trong mã nguồn. Thay vào đó, các khóa được đặt trong manifest và có thể khác nhau cho các biến thể build khác nhau.
Thuộc tính android:extractNativeLibs kiểm soát việc giải nén các thư viện gốc khỏi APK. Đối với các ứng dụng có targetSdk 34+, thuộc tính này phải được chỉ định rõ ràng, nếu không bản dịch có thể thất bại với lỗi INSTALL_FAILED_INVALID_APK. Nếu extractNativeLibs=false, các thư viện gốc vẫn nằm trong APK mà không được giải nén, giảm kích thước ứng dụng đã cài đặt nhưng tăng thời gian tải thư viện. Đối với hầu hết các ứng dụng hiện đại, extractNativeLibs=false được khuyến nghị để giảm dung lượng ổ đĩa trên thiết bị của người dùng.
Thuộc tính android:networkSecurityConfig cho phép chỉ định tệp cấu hình bảo mật mạng. Điều này đặc biệt quan trọng đối với các ứng dụng có targetSdk 28+, nơi lưu lượng HTTP bị chặn theo mặc định. Tệp cấu hình xác định các chứng chỉ đáng tin cậy, tên miền cho kết nối HTTP và các quy tắc ghim chứng chỉ. Điều này thay thế thuộc tính cũ android:usesCleartextTraffic và cung cấp cơ chế linh hoạt hơn để quản lý bảo mật kết nối ở cấp hệ điều hành.
Thuộc tính android:largeHeap yêu cầu kích thước heap tăng lên cho ứng dụng. Theo mặc định, Android phân bổ cho mỗi ứng dụng một lượng bộ nhớ giới hạn tùy thuộc vào thiết bị và phiên bản HĐH. Nếu ứng dụng làm việc với hình ảnh nặng, video hoặc tập dữ liệu lớn, largeHeap có thể ngăn OutOfMemoryError. Tuy nhiên, lạm dụng thuộc tính này sẽ gây hại: ứng dụng có mức tiêu thụ bộ nhớ cao sẽ bị hệ thống kết thúc nhanh hơn khi tài nguyên thấp. Chỉ sử dụng largeHeap sau khi đã phân tích hồ sơ và xác nhận nhu cầu.
Câu hỏi thường gặp
Từ Android 12, việc thiếu thuộc tính exported khi có intent-filter sẽ gây ra lỗi biên dịch. Hệ thống yêu cầu khả năng hiển thị rõ ràng cho mọi thành phần có intent-filter — đây là biện pháp bảo mật để ngăn chặn việc vô tình tiếp xúc các thành phần với các ứng dụng khác. Đối với Activity không có intent-filter, exported mặc định là false.
Có, nhưng trình khởi chạy sẽ hiển thị nhiều biểu tượng ứng dụng. Mỗi Activity với MAIN/LAUNCHER trở thành một điểm vào riêng biệt. Điều này được sử dụng để tạo lối tắt đến các phần khác nhau của ứng dụng, ví dụ để đi thẳng đến cài đặt hoặc tạo bản ghi mới. Mỗi biểu tượng sẽ mở trực tiếp Activity tương ứng.
Android hợp nhất các manifest từ thư viện với manifest chính của ứng dụng. Trong trường hợp xung đột thuộc tính, tools:replace hoặc tools:node=«merge» được sử dụng để giải quyết. Cơ chế này tự động: khi một thư viện được thêm qua Gradle, manifest của nó sẽ được hợp nhất với manifest chính. Để ghi đè hoặc thay thế một thuộc tính từ thư viện, hãy sử dụng tools:node=«remove» hoặc tools:replace=«attributeName».
Các lý do điển hình: quyền không được khai báo trong manifest qua uses-permission, đó là quyền cấp độ bình thường (không cần yêu cầu runtime), người dùng đã chọn «Không hỏi lại» và quyền đã bị từ chối vĩnh viễn, hoặc targetSdkVersion dưới 23 nơi quyền được yêu cầu khi cài đặt. Để chẩn đoán, hãy kiểm tra manifest và nhật ký qua adb logcat.
Thuộc tính android:debuggable bật tính năng gỡ lỗi ứng dụng qua ADB. Đối với các bản dựng phát hành trên Google Play, nó phải là false. Nếu debuggable=true trong bản dựng phát hành, kẻ tấn công có thể kết nối với ứng dụng qua ADB, đọc dữ liệu và thực thi mã tùy ý. Google Play tự động chặn việc xuất bản các bản dựng có debuggable=true.
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm