AndroidManifest 详解
本教程共 100 篇 · 第 22 篇 · 更新于 2026-07-28 · 约 9 分钟阅读
22. AndroidManifest 详解
本节目标:看懂 AndroidManifest.xml 的每个标签和属性,会注册组件、声明权限、配置应用元数据,知道 Manifest 在构建和运行时干什么。
Manifest 是什么
AndroidManifest.xml 是应用的「身份证」和「说明书」,每个应用必须有一个,放在 app/src/main/ 下。它告诉系统和 Google Play:
- 应用有哪些组件(Activity、Service、Receiver、Provider)。
- 需要什么权限。
- 需要什么硬件软件特性(影响哪些设备能装)。
- 应用图标、名称、主题等元数据。
- 最低 SDK 版本(虽然现在主要在 build.gradle 声明)。
没在 Manifest 声明的组件,系统不认,启动会崩溃。
整体结构
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 权限声明 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- 硬件软件特性 -->
<uses-feature android:name="android.hardware.camera" android:required="true" />
<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">
<!-- 四大组件 -->
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".DetailActivity" />
<service android:name=".DownloadService" />
<receiver android:name=".BootReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<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="YOUR_API_KEY" />
</application>
</manifest>
下面逐块拆解。
manifest 根标签
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
xmlns:android:声明 android 命名空间,必须。package:旧版本写包名的地方。新版 Gradle 项目改用build.gradle的namespace,Manifest 里不写package。
权限声明 uses-permission
应用要访问系统功能必须声明权限:
<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-permission android:name="android.permission.POST_NOTIFICATIONS" />
权限分两类:
- 普通权限:安装时自动授权,如
INTERNET。 - 危险权限:运行时要用户授权,如
CAMERA、READ_CONTACTS、POST_NOTIFICATIONS。第 83 章细讲。
maxSdkVersion 表示这个权限只在某个 SDK 以下需要。比如分区存储后,READ_EXTERNAL_STORAGE 在 API 33+ 不再需要。
硬件软件特性 uses-feature
声明应用需要或可选的硬件特性,影响 Google Play 上哪些设备能看到应用:
<!-- 必须有相机,否则装不了 -->
<uses-feature android:name="android.hardware.camera" android:required="true" />
<!-- 可选,有则用,没有也能装 -->
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="false" />
Tip
- 想让应用在没相机的设备也能装,把相机设
required="false",代码里运行时判断PackageManager.hasSystemFeature()。
application 标签
应用级别的配置,一个 Manifest 只有一个:
<application
android:name=".MyApplication" <!-- 自定义 Application 类 -->
android:allowBackup="true" <!-- 允许备份 -->
android:icon="@mipmap/ic_launcher" <!-- 应用图标 -->
android:label="@string/app_name" <!-- 应用名称 -->
android:roundIcon="@mipmap/ic_launcher_round" <!-- 圆形图标 -->
android:supportsRtl="true" <!-- 支持 RTL(阿拉伯语等) -->
android:theme="@style/Theme.MyApp" <!-- 默认主题 -->
android:usesCleartextTraffic="false"> <!-- 是否允许 HTTP 明文 -->
常用属性:
android:name:自定义Application子类,应用启动时最先创建。需要全局初始化(如 SDK、日志)时用。android:usesCleartextTraffic:默认false,禁止 HTTP 明文,强制 HTTPS。要联老服务器 HTTP 接口设true。android:networkSecurityConfig:更精细的网络安全配置(XML 文件)。
Activity 声明
每个 Activity 都要声明:
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/Theme.MyApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
属性:
android:name:类名,.开头表示相对 namespace。android:exported:是否能被其他应用启动。Android 12+ 必须显式声明,启动 Activity 要设true。MAIN+LAUNCHER的入口 Activity 必须true。android:launchMode:启动模式(第 27 章讲)。android:screenOrientation:屏幕方向。
intent-filter
声明这个 Activity 能响应什么 Intent。入口 Activity 的 filter:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
MAIN + LAUNCHER 表示这是桌面图标启动的入口。第 30 章细讲 intent-filter。
Service 声明
<service
android:name=".MusicService"
android:exported="false"
android:foregroundServiceType="mediaPlayback" />
Warning
- Android 14(API 34)起,所有前台服务必须声明
foregroundServiceType,类型有mediaPlayback、dataSync、location、camera、microphone等,启动时要对应权限。不声明直接崩溃。第 33 章细讲。
Receiver 声明
<receiver
android:name=".BootReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
静态注册的 Receiver 在 Manifest 声明。Android 8.0 起大部分系统广播只能动态注册,只有少数(如 BOOT_COMPLETED)能静态注册。
Provider 声明
<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>
authorities:唯一标识,通常用包名加后缀。${applicationId}是 Manifest 占位符,编译时替换。grantUriPermissions:是否允许临时授权给其他应用访问 URI。
FileProvider 是最常用的 Provider,分享文件给其他应用时用。
meta-data
给组件或应用附加任意键值对配置,第三方 SDK 常用:
<application>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSy..." />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />
</application>
代码里读取:
val ai = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)
val apiKey = ai.metaData.getString("com.google.android.geo.API_KEY")
Manifest 占位符
build.gradle 里定义占位符,Manifest 里用 ${} 引用:
defaultConfig {
manifestPlaceholders["appLabel"] = "我的应用"
manifestPlaceholders["appAuth"] = "com.example.app.provider"
}
<application android:label="${appLabel}">
<provider android:authorities="${appAuth}" />
不同 flavor 用不同值时很有用。
Manifest 合并
最终 APK 里只有一个 Manifest,但项目有多个来源:
- 主源集
src/main/AndroidManifest.xml。 - 各 flavor 的
src/free/AndroidManifest.xml。 - 各 BuildType 的
src/debug/AndroidManifest.xml。 - 依赖库的 Manifest。
构建时 Gradle 把它们合并成一个。合并规则:标签按属性合并,冲突时用 merge 规则标记解决(tools:replace、tools:remove)。
<uses-permission android:name="android.permission.INTERNET"
tools:node="remove" /> <!-- 移除依赖库带来的这个权限 -->
Android Studio 点 Merged Manifest 能看合并结果,排查冲突很方便。
常见踩坑
组件没声明
ActivityNotFoundException: Unable to find explicit activity class
新建 Activity 忘了在 Manifest 声明。Android Studio 用向导新建会自动加,手动建文件要自己加。
exported 没声明
Android 12+ 报错:
Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined
所有带 intent-filter 的组件必须显式声明 android:exported。
权限没声明就用了
调相机没声明 CAMERA 权限,运行时请求权限失败或直接崩溃。危险权限不仅要声明,还要运行时请求。
小结
Manifest 声明应用组件、权限、特性、元数据。application 配置全局属性,四大组件各有对应标签,intent-filter 描述能响应的 Intent,meta-data 附加配置,占位符和合并机制支持多 flavor。组件必须声明才能用,Android 12+ 要显式 exported。下一节学资源体系。