Manifest Components
The AndroidManifest.xml
Every Android app must have an AndroidManifest.xml in the root directory. It declares:
- App components (Activity, Service, Receiver, Provider)
- Permissions the app needs
- Minimum and target SDK versions
- Hardware/software features required
- Application metadata
Component Declarations
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<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">
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:theme="@style/Theme.MyApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.WebActivity"
android:exported="false" />
<service
android:name=".service.SyncService"
android:exported="false"
android:foregroundServiceType="dataSync" />
<receiver
android:name=".receiver.DownloadReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.example.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
<provider
android:name=".data.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>
</application>
</manifest>
Exported Components
Since Android 12 (API 31), any component with an intent filter must explicitly declare android:exported. Components without intent filters default to exported="false".
exported="true": Accessible by other apps (launcher activity, deep link handler, content provider)exported="false": Private to your app only
Application Tag Attributes
| Attribute | Purpose |
|---|---|
android:name |
Custom Application class |
android:allowBackup |
Enable/disable ADB backup |
android:icon |
App icon |
android:label |
App name |
android:theme |
Default theme for all activities |
android:supportsRtl |
Right-to-left layout support |
Permissions
Android Permissions
Android uses a permission model to protect user privacy. Permissions are categorized by risk level.
Permission Categories
| Category | Behavior | Example |
|---|---|---|
| Normal | Granted automatically at install | INTERNET, VIBRATE |
| Dangerous | Requires runtime approval | CAMERA, READ_CONTACTS, LOCATION |
| Signature | Granted only if same signing key | SYSTEM_ALERT_WINDOW |
Declaring Permissions
<!-- In manifest -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
Requesting Runtime Permissions
Dangerous permissions must be requested at runtime:
class CameraActivity : AppCompatActivity() {
private val requestPermission = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted ->
if (granted) {
openCamera()
} else {
showPermissionRationale()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
findViewById<Button>(R.id.btnCamera).setOnClickListener {
when {
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED -> {
openCamera()
}
shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
showPermissionRationale()
}
else -> {
requestPermission.launch(Manifest.permission.CAMERA)
}
}
}
}
}
Permission Groups
Related permissions are grouped. If one permission in a group is granted, related ones may be auto-granted:
- CONTACTS: READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS
- LOCATION: ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION
- CAMERA: CAMERA
- STORAGE: READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO
Multi-Permission Requests
val requestMultiplePermissions = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
val cameraGranted = permissions[Manifest.permission.CAMERA] ?: false
val locationGranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false
if (cameraGranted && locationGranted) {
startFeature()
}
}
requestMultiplePermissions.launch(arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION
))
Declaring Custom Permissions
Apps can define their own permissions:
<permission
android:name="com.example.MY_PERMISSION"
android:protectionLevel="normal"
android:label="Custom Permission"
android:description="Required to access custom features" />
Use protectionLevel carefully — dangerous forces other apps to request it at runtime.
Quiz
1. Why must components with intent filters declare android:exported?
2. What is the difference between normal and dangerous permissions?
3. When should you use shouldShowRequestPermissionRationale()?
4. What is the purpose of android:maxSdkVersion in a permission declaration?
Flashcards
Question
What does android:exported control?
Click to reveal answer
Answer
Whether a component can be started by other apps. true = accessible externally, false = private to your app.
Question
When do you need runtime permission requests?
Click to reveal answer
Answer
For dangerous permissions (CAMERA, LOCATION, CONTACTS, STORAGE). Normal permissions (INTERNET) are granted automatically at install.
Question
What is the android:name attribute on the application tag?
Click to reveal answer
Answer
It specifies a custom Application subclass that gets created before any activity — use for app-wide initialization, dependency injection, and global state.
Question
How do you check if a permission is already granted?
Click to reveal answer
Answer
ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
Revision Notes
Key Takeaways
- 1. AndroidManifest declares all app components, permissions, and configuration
- 2. Since Android 12, components with intent filters must explicitly declare exported
- 3. Dangerous permissions require runtime requests using the Activity Result API
- 4. Always check shouldShowRequestPermissionRationale before re-requesting
- 5. The Application class initializes before any activity — use for global setup
Interview Tips
- • Know the four component types and when to use each
- • Explain the exported attribute and why it matters for security
- • Be ready to write runtime permission request code from memory
- • Discuss how to handle permission denial gracefully
Cheat Sheet
AndroidManifest Cheat Sheet
Components:
Activity— UI screenService— background workBroadcastReceiver— system/app eventsContentProvider— data sharing
Key Attributes:
exported— external accessibilityintent-filter— what intents it handlesforegroundServiceType— service type for Android 14+
Permissions:
- Normal: auto-granted at install
- Dangerous: runtime request needed
- Check:
ContextCompat.checkSelfPermission() - Request:
registerForActivityResult
Android 12+ Requirement:
- Components with intent filters MUST declare
exported