Skip to Content

AndroidManifest.xml

1. Giới thiệu

AndroidManifest.xml là file cấu hình bắt buộc cho mọi ứng dụng Android. File này cung cấp thông tin thiết yếu về ứng dụng cho hệ thống Android, bao gồm:

  • Package name: Định danh duy nhất của ứng dụng
  • Components: Các Activity, Service, BroadcastReceiver, ContentProvider
  • Permissions: Quyền truy cập tài nguyên hệ thống
  • Hardware/Software features: Yêu cầu phần cứng/phần mềm
  • API levels: Phiên bản Android được hỗ trợ

Vị trí file: app/src/main/AndroidManifest.xml

2. Cấu trúc cơ bản

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- Permissions - Quyền truy cập --> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApp" tools:targetApi="31"> <activity android:name=".MainActivity" ... /> </application> </manifest>

Giải thích các namespace:

NamespaceMục đích
xmlns:androidChứa các thuộc tính Android chuẩn
xmlns:toolsChứa các thuộc tính chỉ dùng cho build time, không đi vào APK

3. Permissions (Quyền truy cập)

3.1 Phân loại Permissions

LoạiMô tảVí dụ
NormalCấp tự động, không cần hỏi userINTERNET, VIBRATE
DangerousPhải xin quyền runtime từ Android 6.0+CAMERA, LOCATION
SignatureChỉ cấp cho apps có cùng signatureBIND_DEVICE_ADMIN

3.2 Internet Permission

<uses-permission android:name="android.permission.INTERNET" />

Khi nào cần?

  • Gọi API REST/GraphQL
  • Tải ảnh từ internet (Glide, Coil, Picasso)
  • WebView load URL
  • Firebase, Analytics, Ads
  • Real-time messaging (WebSocket)

Ví dụ thực tế: App tin tức cần load danh sách bài viết từ server.


3.3 Camera Permission

<uses-permission android:name="android.permission.CAMERA" />

Khi nào cần?

  • Chụp ảnh/quay video trực tiếp trong app
  • Quét QR code/barcode
  • AR (Augmented Reality) features
  • Video call

Ví dụ thực tế: App ngân hàng cần quét mã QR để thanh toán.

⚠️ Lưu ý: Đây là Dangerous permission - cần xin quyền runtime từ Android 6.0+

// Request permission at runtime if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CODE) }

3.4 Location Permission

<!-- Vị trí chính xác (GPS) - độ chính xác cao --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Vị trí xấp xỉ (Network) - tiết kiệm pin --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Foreground location (Android 10+) --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <!-- Background location (Android 10+) - cần giải thích rõ cho user --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Sự khác biệt:

PermissionĐộ chính xácUse case
FINE_LOCATION~1-10m (GPS)Bản đồ điều hướng, giao nhận
COARSE_LOCATION~100m (Network)Thời tiết, tin tức địa phương
BACKGROUND_LOCATIONCả 2Fitness tracking, geo-fencing

Ví dụ thực tế:

  • Grab/Gojek: Cần FINE_LOCATION + BACKGROUND_LOCATION để tracking realtime
  • Weather app: Chỉ cần COARSE_LOCATION để lấy thời tiết thành phố

3.5 Storage Permission

<!-- Đọc file từ bộ nhớ --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Ghi file vào bộ nhớ --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <!-- Android 13+ (API 33): Media permissions chi tiết --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

Thay đổi qua các phiên bản Android:

AndroidCách tiếp cận Storage
≤ 9 (API 28)READ/WRITE_EXTERNAL_STORAGE
10 (API 29)Scoped Storage + requestLegacyExternalStorage
11-12 (API 30-32)Scoped Storage bắt buộc
13+ (API 33)READ_MEDIA_* permissions

Ví dụ thực tế: App gallery cần đọc ảnh từ thư viện máy.

// Android 13+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { requestPermissions(arrayOf(Manifest.permission.READ_MEDIA_IMAGES)) } else { requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)) }

3.6 Notification Permission (Android 13+)

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Khi nào cần?

  • Push notifications
  • Local notifications (nhắc nhở, alarm)
  • Download progress notifications
  • Music playback controls

Lưu ý: Từ Android 13, notifications cũng cần xin quyền runtime!

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) } }

3.7 Các Permission thường dùng khác

<!-- Rung điện thoại --> <uses-permission android:name="android.permission.VIBRATE" /> <!-- Giữ màn hình sáng --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Nhận sự kiện boot completed --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- Bluetooth --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 12+ --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- Android 12+ --> <!-- Đọc contacts --> <uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- Gọi điện --> <uses-permission android:name="android.permission.CALL_PHONE" /> <!-- Đọc trạng thái điện thoại --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- Ghi âm --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- Biometric (vân tay, face) --> <uses-permission android:name="android.permission.USE_BIOMETRIC" />

4. Application Tag

<application android:name=".MyApplication" android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApp" android:networkSecurityConfig="@xml/network_security_config" android:usesCleartextTraffic="false" android:largeHeap="false"> <!-- Components here --> </application>

Giải thích chi tiết từng thuộc tính:

Thuộc tínhMô tảVí dụ khi cần
android:nameClass Application tùy chỉnhKhởi tạo DI (Hilt/Koin), Firebase, Timber
android:allowBackupCho phép backup data lên Google Drivefalse cho apps banking/sensitive
android:iconIcon hiển thị trên launcherMọi app
android:roundIconIcon tròn cho các launcher hỗ trợPixel, Samsung One UI
android:labelTên app hiển thịMọi app
android:themeTheme mặc định cho appMaterial Theme
android:supportsRtlHỗ trợ ngôn ngữ Right-to-LeftArabic, Hebrew
android:networkSecurityConfigCấu hình bảo mật mạngDebug với localhost
android:usesCleartextTrafficCho phép HTTP không mã hóafalse cho production
android:largeHeapYêu cầu heap memory lớn hơnXử lý ảnh/video lớn

Ví dụ Custom Application class:

class MyApplication : Application() { override fun onCreate() { super.onCreate() // Khởi tạo các libraries if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) } // Firebase FirebaseApp.initializeApp(this) // Crash reporting FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG) } }

5. Activity

5.1 Main Activity (Launcher)

<activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.MyApp" android:launchMode="singleTop" android:screenOrientation="portrait" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>

Giải thích Intent Filter:

  • action.MAIN: Đây là entry point của app
  • category.LAUNCHER: Hiển thị icon trên launcher/app drawer

5.2 Các thuộc tính Activity quan trọng

Thuộc tínhGiá trịMô tảKhi nào dùng
exportedtrue/falseCho phép components khác khởi độngtrue cho launcher, deep link
launchModestandardTạo instance mới mỗi lầnDefault
singleTopDùng lại nếu đang ở top stackNotification click
singleTaskChỉ 1 instance trong taskMain screen
singleInstanceInstance riêng biệtIncoming call screen
screenOrientationportraitChỉ dọcForm nhập liệu
landscapeChỉ ngangGame, video player
fullSensorTheo sensorGallery viewer
windowSoftInputModeadjustResizeResize layout khi keyboard xuất hiệnChat input
adjustPanPan lên để hiện inputLogin form
configChangesorientation|screenSizeKhông recreate khi config changeVideo player

5.3 Activity thường (Internal)

<activity android:name=".DetailActivity" android:exported="false" android:parentActivityName=".MainActivity" android:theme="@style/Theme.MyApp"> <!-- Enable Up navigation automatically --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity" /> </activity>

Khi nào dùng exported="false"?

  • Activity chỉ được mở từ trong app
  • Không cần deep link hay external access
  • Bảo mật: ngăn apps khác khởi động activity này
<activity android:name=".ProductActivity" android:exported="true"> <!-- App Links (HTTPS - verified) --> <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="www.mystore.com" android:pathPrefix="/product" /> </intent-filter> <!-- Custom Scheme (không cần verify) --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" android:host="product" /> </intent-filter> </activity>

Các loại Deep Link:

LoạiSchemeVerifyVí dụ URL
App LinkshttpsCần verify domainhttps://mystore.com/product/123
Deep Linkshttp/httpsKhônghttp://mystore.com/product/123
Custom SchemeCustomKhôngmyapp://product/123

Ví dụ thực tế:

  • E-commerce: https://shopee.vn/product/123 → mở app Shopee
  • Email verification: myapp://verify?token=abc → mở màn hình verify
class ProductActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Handle deep link handleIntent(intent) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) intent?.let { handleIntent(it) } } private fun handleIntent(intent: Intent) { val data: Uri? = intent.data data?.let { val productId = it.lastPathSegment // "123" from /product/123 loadProduct(productId) } } }

6. Service

6.1 Background Service

<service android:name=".DownloadService" android:exported="false" android:enabled="true" />

Khi nào cần?

  • Download/upload files trong background
  • Sync data với server
  • Các tác vụ không cần UI

6.2 Foreground Service

<service android:name=".MusicPlayerService" android:foregroundServiceType="mediaPlayback" android:exported="false" /> <service android:name=".LocationTrackingService" android:foregroundServiceType="location" android:exported="false" /> <service android:name=".UploadService" android:foregroundServiceType="dataSync" android:exported="false" />

Foreground Service Types (Android 10+):

TypePermission cần thêmVí dụ
cameraFOREGROUND_SERVICE_CAMERAVideo recording
connectedDeviceFOREGROUND_SERVICE_CONNECTED_DEVICEBluetooth device
dataSyncFOREGROUND_SERVICE_DATA_SYNCCloud sync
healthFOREGROUND_SERVICE_HEALTHFitness tracking
locationFOREGROUND_SERVICE_LOCATIONGPS tracking
mediaPlaybackFOREGROUND_SERVICE_MEDIA_PLAYBACKMusic player
mediaProjectionFOREGROUND_SERVICE_MEDIA_PROJECTIONScreen recording
microphoneFOREGROUND_SERVICE_MICROPHONEVoice recording
phoneCallFOREGROUND_SERVICE_PHONE_CALLVoIP
remoteMessagingFOREGROUND_SERVICE_REMOTE_MESSAGINGPush notifications
shortService-Quick tasks < 3 mins
specialUseFOREGROUND_SERVICE_SPECIAL_USEOther cases

Ví dụ thực tế - Music Player:

class MusicPlayerService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val notification = createNotification() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK) } else { startForeground(NOTIFICATION_ID, notification) } // Play music... return START_STICKY } }

6.3 Bound Service

<service android:name=".MessengerService" android:exported="false"> <intent-filter> <action android:name="com.example.messenger.BIND" /> </intent-filter> </service>

Khi nào dùng?

  • Cần giao tiếp hai chiều giữa Activity và Service
  • Multiple clients bind to same service
  • AIDL cho inter-process communication

7. Broadcast Receiver

7.1 Static Registration (Manifest)

<receiver android:name=".BootCompletedReceiver" android:exported="true" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>

Khi nào dùng Static?

  • Nhận broadcasts khi app không chạy
  • System broadcasts: BOOT_COMPLETED, PACKAGE_ADDED
  • Cần guaranteed delivery

7.2 Các System Broadcasts phổ biến

<!-- Khi device boot xong --> <receiver android:name=".BootReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <!-- Khi timezone/time thay đổi --> <receiver android:name=".TimeChangeReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.TIMEZONE_CHANGED" /> <action android:name="android.intent.action.TIME_SET" /> </intent-filter> </receiver> <!-- Khi battery low --> <receiver android:name=".BatteryReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BATTERY_LOW" /> <action android:name="android.intent.action.BATTERY_OKAY" /> </intent-filter> </receiver> <!-- Khi network thay đổi (deprecated, dùng NetworkCallback) --> <receiver android:name=".NetworkReceiver" android:exported="true"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver>

Lưu ý Android 8.0+: Nhiều implicit broadcasts bị hạn chế. Nên dùng:

  • Dynamic registration (trong code)
  • JobScheduler / WorkManager

7.3 Dynamic Registration (Trong Code)

class MainActivity : AppCompatActivity() { private val screenReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { when (intent.action) { Intent.ACTION_SCREEN_ON -> handleScreenOn() Intent.ACTION_SCREEN_OFF -> handleScreenOff() } } } override fun onResume() { super.onResume() val filter = IntentFilter().apply { addAction(Intent.ACTION_SCREEN_ON) addAction(Intent.ACTION_SCREEN_OFF) } registerReceiver(screenReceiver, filter) } override fun onPause() { super.onPause() unregisterReceiver(screenReceiver) } }

8. Content Provider

8.1 FileProvider (Chia sẻ files)

<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>

File res/xml/file_paths.xml:

<?xml version="1.0" encoding="utf-8"?> <paths> <!-- Internal app storage: /data/data/com.example/files/ --> <files-path name="internal_files" path="." /> <!-- Internal cache: /data/data/com.example/cache/ --> <cache-path name="cache" path="." /> <!-- External files: /storage/emulated/0/Android/data/com.example/files/ --> <external-files-path name="external_files" path="." /> <!-- External cache --> <external-cache-path name="external_cache" path="." /> <!-- External storage root (deprecated) --> <external-path name="external" path="." /> <!-- Specific subdirectory --> <files-path name="images" path="images/" /> </paths>

Ví dụ thực tế - Share image:

fun shareImage(context: Context, imageFile: File) { val uri = FileProvider.getUriForFile( context, "${context.packageName}.fileprovider", imageFile ) val shareIntent = Intent(Intent.ACTION_SEND).apply { type = "image/*" putExtra(Intent.EXTRA_STREAM, uri) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } context.startActivity(Intent.createChooser(shareIntent, "Share via")) }

8.2 Custom Content Provider

<provider android:name=".data.NotesProvider" android:authorities="com.example.app.provider" android:exported="true" android:permission="com.example.app.READ_NOTES"> <path-permission android:pathPrefix="/notes" android:readPermission="com.example.app.READ_NOTES" android:writePermission="com.example.app.WRITE_NOTES" /> </provider>

Khi nào cần Custom Provider?

  • Chia sẻ data với apps khác
  • Sync data với system (Contacts, Calendar)
  • Search integration

9. Hardware Features

<!-- Camera bắt buộc - app sẽ không hiện trên devices không có camera --> <uses-feature android:name="android.hardware.camera" android:required="true" /> <!-- Camera tùy chọn - app vẫn hiện nhưng có thể kiểm tra runtime --> <uses-feature android:name="android.hardware.camera" android:required="false" /> <!-- GPS --> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <!-- Bluetooth --> <uses-feature android:name="android.hardware.bluetooth" android:required="false" /> <!-- NFC --> <uses-feature android:name="android.hardware.nfc" android:required="false" /> <!-- Fingerprint --> <uses-feature android:name="android.hardware.fingerprint" android:required="false" /> <!-- Telephony (cho phone apps) --> <uses-feature android:name="android.hardware.telephony" android:required="false" /> <!-- Microphone --> <uses-feature android:name="android.hardware.microphone" android:required="true" />

Kiểm tra feature runtime:

fun hasCameraFeature(context: Context): Boolean { return context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA) } fun hasNfcFeature(context: Context): Boolean { return context.packageManager.hasSystemFeature(PackageManager.FEATURE_NFC) }

Ví dụ thực tế:

  • QR Scanner app: camera required = true
  • E-commerce app: camera required = false (có thể dùng để scan QR nhưng không bắt buộc)

10. Screen Configurations

<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" android:resizeable="true" />

Ý nghĩa:

Thuộc tínhScreen sizeVí dụ device
smallScreens< 3”Smartwatch (hiếm)
normalScreens3” - 5”Hầu hết phones
largeScreens5” - 7”Tablets nhỏ
xlargeScreens7”+Tablets lớn

Compatible screens (giới hạn devices):

<compatible-screens> <!-- Chỉ hỗ trợ normal screens với hdpi, xhdpi, xxhdpi --> <screen android:screenSize="normal" android:screenDensity="hdpi" /> <screen android:screenSize="normal" android:screenDensity="xhdpi" /> <screen android:screenSize="normal" android:screenDensity="xxhdpi" /> </compatible-screens>

11. Meta-data

11.1 Google Services

<application> <!-- Google Maps API Key --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="${MAPS_API_KEY}" /> <!-- Google Play Services version check --> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> </application>

11.2 Firebase

<application> <!-- Default notification icon --> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_notification" /> <!-- Default notification color --> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" /> <!-- Default notification channel --> <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="default_channel" /> </application>

11.3 Facebook SDK

<application> <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id" /> <meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token" /> </application>

11.4 AdMob

<application> <meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-xxxxxxxx~xxxxxxxx" /> </application>

12. Network Security Config

Tạo file res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?> <network-security-config> <!-- Base config cho tất cả domains --> <base-config cleartextTrafficPermitted="false"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config> <!-- Cho phép cleartext cho localhost (development) --> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">localhost</domain> <domain includeSubdomains="true">10.0.2.2</domain> <domain includeSubdomains="true">192.168.1.0</domain> </domain-config> <!-- Debug-only: trust user-installed certificates --> <debug-overrides> <trust-anchors> <certificates src="user" /> <certificates src="system" /> </trust-anchors> </debug-overrides> </network-security-config>

Khai báo trong manifest:

<application android:networkSecurityConfig="@xml/network_security_config">

Khi nào cần?

ScenarioConfig
Development với localhostcleartextTrafficPermitted="true" cho localhost
ProductioncleartextTrafficPermitted="false" (chỉ HTTPS)
Certificate pinningThêm <pin-set>
Charles Proxy debuggingdebug-overrides với user certificates

Certificate Pinning:

<domain-config> <domain includeSubdomains="true">api.myapp.com</domain> <pin-set expiration="2025-12-31"> <pin digest="SHA-256">base64EncodedPublicKeyHash1=</pin> <pin digest="SHA-256">base64EncodedPublicKeyHash2=</pin> </pin-set> </domain-config>

13. Queries (Android 11+)

Từ Android 11, cần khai báo package visibility:

<queries> <!-- Specific packages --> <package android:name="com.facebook.katana" /> <package android:name="com.twitter.android" /> <!-- Apps that handle specific intents --> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="https" /> </intent> <!-- Apps that handle sharing --> <intent> <action android:name="android.intent.action.SEND" /> <data android:mimeType="image/*" /> </intent> <!-- Apps that can take photos --> <intent> <action android:name="android.media.action.IMAGE_CAPTURE" /> </intent> </queries>

Khi nào cần?

  • Kiểm tra app khác có được cài không (isPackageInstalled)
  • Mở app khác (startActivity với package name)
  • Share content tới specific apps

14. Ví dụ Manifest hoàn chỉnh

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- Permissions --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <!-- Features --> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <!-- Package visibility (Android 11+) --> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="https" /> </intent> </queries> <application android:name=".MyApplication" android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApp" android:networkSecurityConfig="@xml/network_security_config" tools:targetApi="34"> <!-- Main Activity --> <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/Theme.MyApp.Splash"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- Deep Links --> <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="myapp.com" /> </intent-filter> </activity> <!-- Other Activities --> <activity android:name=".DetailActivity" android:exported="false" android:parentActivityName=".MainActivity" /> <!-- Services --> <service android:name=".LocationService" android:foregroundServiceType="location" android:exported="false" /> <!-- Receivers --> <receiver android:name=".BootReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <!-- Providers --> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> <!-- Meta-data --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="${MAPS_API_KEY}" /> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_notification" /> </application> </manifest>

📝 Tóm tắt

ElementMục đíchVí dụ thực tế
<uses-permission>Khai báo quyền cần thiếtInternet, Camera, Location
<uses-feature>Khai báo yêu cầu hardwareCamera required/optional
<application>Cấu hình app toàn cụcIcon, theme, Application class
<activity>Màn hình UILauncher, Deep links
<service>Background processingMusic player, Downloads
<receiver>Nhận broadcastsBoot completed, Battery
<provider>Chia sẻ dataFileProvider cho sharing
<meta-data>Config bổ sungAPI keys, Firebase
<queries>Package visibility (API 30+)Check installed apps

Best Practices:

  1. Chỉ khai báo permissions thực sự cần - ít permission = ít risk
  2. Dùng android:required="false" cho features tùy chọn
  3. Set exported="false" cho components internal
  4. Sử dụng Network Security Config đúng cách cho production
  5. Khai báo <queries> cho Android 11+ nếu cần package visibility
Last updated on