AndroidManifest.xml 是每个 Android 应用必须提供的基础配置文件,它不参与业务逻辑运行,却决定了应用能否被系统正确识别、安装和拉起。系统 PackageManager 在安装 APK 时会解析该文件中的包名、版本号、组件声明和权限信息,如果声明缺失或格式错误,轻则组件无法启动,重则安装失败。理解 Manifest 的作用,是构建稳定 Android 应用的第一步。

Manifest 承担四个核心职责:声明应用包名和版本、注册四大组件、申请系统权限、声明应用运行所需的硬件和软件特性。比如没有在 Manifest 中声明 Activity,调用 startActivity 时系统会找不到目标组件并抛出 ActivityNotFoundException。这解释了为什么新建 Activity 后必须同步注册。
一、Manifest.xml 的基础作用与根节点结构
Manifest 的根节点是 <manifest>。在传统项目结构中,根节点的 package 属性用来标记应用唯一包名,较新的 AGP 版本已经推荐使用 Gradle 中的 namespace 替代该属性,但很多现有工程仍然保留。根节点下通常包含 <uses-permission>、<application>、<uses-feature> 等一级子节点。系统解析时只关心声明的信息,不会去扫描 Java 或 Kotlin 源文件,所以即便代码中存在某个 Activity 类,只要没有注册到 Manifest,系统也无法直接启动它。
根节点中的 xmlns:android 命名空间必须指向官方地址,命名空间出错会导致整个文件解析失败。版本信息 versionCode 与 versionName 虽然在 Gradle 脚本中也可以配置,但不少团队仍保留在 Manifest 中,便于查看安装包的基础信息。对于启动入口,系统通过带有 MAIN action 和 LAUNCHER category 的 Activity 决定桌面图标点击后打开的界面。这个配置如果重复出现在多个 Activity 上,桌面会生成多个入口图标。
以下是一个基础结构的示例,展示了根节点、权限声明和应用节点的组织方式:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.demo">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这个示例中,<uses-permission> 声明了网络权限,<application> 配置了应用图标、名称和主题,<activity> 声明了 MainActivity 并将其设置为桌面启动入口。没有这个入口声明,应用安装后不会在桌面显示图标。
二、核心配置项详解:application 与四大组件
<application> 是全局应用配置节点,图标、名称、主题、是否允许备份、是否支持多窗口等属性都写在这里。allowBackup 如果为 true,用户数据可能被 adb backup 导出;debuggable 一旦打开,攻击者可以动态调试应用,因此发布版本必须关闭。android:name 属性可以指定自定义 Application 子类,用于全局初始化。该节点还承载四大组件的注册,所有组件标签都必须写在 application 节点内,否则会解析失败。
Activity 是最常见的组件,每个 Activity 都要用 <activity> 声明,android:name 可以使用完整类名,也可以使用相对包名的点号开头,例如 .MainActivity。启动模式、屏幕方向、是否全屏等可以通过属性控制。通过 <intent-filter> 可以为 Activity 声明隐式跳转入口,例如打开网页、分享文本等。若未配置 intent-filter,则只能通过显式类名跳转,无法被外部应用唤起。
Service 和 BroadcastReceiver 的声明方式类似,分别使用 <service> 和 <receiver> 标签。Service 一般用于后台任务,BroadcastReceiver 用于接收系统或应用广播。ContentProvider 使用 <provider> 标签声明,并且必须配置 authorities,它是跨应用访问数据的唯一标识,多个应用如果声明相同的 authorities 会导致安装冲突。下面是一个相对完整的组件注册示例:
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<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>
<service android:name=".DownloadService"
android:exported="false" />
<receiver android:name=".NetworkReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<provider
android:name=".AppContentProvider"
android:authorities="com.example.demo.provider"
android:exported="false" />
</application>
Android 12 及更高版本对组件导出的要求更严格,带有 intent-filter 的 Activity、Service 或 Receiver 必须显式声明 android:exported 属性,否则系统会拒绝安装应用。exported 为 true 表示允许其他应用唤起,为 false 则只在本应用内部使用。这个变化让很多老项目升级后出现安装失败的问题。
三、权限声明与 Manifest 合并机制
Android 权限分为普通权限和危险权限。普通权限如 android.permission.INTERNET 在 Manifest 中声明后安装即授予;危险权限如 android.permission.CAMERA、android.permission.READ_CONTACTS 在 Android 6.0 以上还需要运行时动态申请。如果 Manifest 中未声明危险权限,即使代码里调用 requestPermissions,系统也会直接拒绝,因此静态声明与动态申请两者缺一不可。
权限声明使用 <uses-permission> 标签,android:name 必须是系统定义的完整权限字符串。为了兼容低版本,可以使用 android:maxSdkVersion 属性限制权限只在某版本前申请。但权限不是越多越好,Google Play 上架会审核权限用途,过度申请可能导致应用被拒。如果应用需要相机、蓝牙等硬件能力,还应该声明 <uses-feature>,这样应用商店可以据此过滤不兼容设备。
实际项目中,主 Manifest 与依赖库、构建变体的 Manifest 会按照优先级进行合并。当主 Manifest 与 AAR 依赖中声明了同一个组件或属性时,Gradle 的 manifest merger 会根据冲突类型决定合并结果,严重冲突会直接报错。例如某个第三方 SDK 的 Manifest 声明了 allowBackup 为 true,主应用希望关闭备份,就需要使用 tools:replace 来覆盖默认规则。示例写法如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.demo">
<application
android:allowBackup="false"
tools:replace="android:allowBackup">
</application>
</manifest>
合并后的最终 Manifest 可以在 build/intermediates/merged_manifests 目录下找到,排查权限冲突或组件重复问题时,查看这个文件往往能快速定位最终生效的声明内容。
四、常见配置错误与最佳实践
最典型的错误是新建 Activity 后忘记注册。开发者写完布局和逻辑后直接跳转,日志中会出现 ActivityNotFoundException,此时应第一时间检查 Manifest 中是否存在对应的 <activity> 节点。另一个常见问题是包名与 Gradle applicationId 不一致,部分第三方 SDK 在初始化时会读取 applicationId,与 Manifest 中声明不一致会导致初始化失败或回调异常。
重复声明 launcher Activity 也是常见隐患。多个 Activity 同时声明 MAIN 和 LAUNCHER,会在桌面生成多个入口图标,影响用户体验。有的开发者为了测试方便临时给某个 Activity 配置了启动入口,上线前忘记移除,导致用户看到两个图标。此外,ContentProvider 的 authorities 冲突在多模块或组件化工程中频繁发生,需要统一命名规范,例如使用应用包名加模块名作为前缀。
最佳实践上,建议保持 Manifest 精简,版本号、命名空间等信息尽量由 Gradle 统一管理,避免多处维护。组件名称统一使用相对包名,避免写死完整包名导致重构时遗漏。对于危险权限,应遵循最小化原则,能用系统 Intent 打开的选择器就不申请权限。每次构建后可以检查 merged manifest,确认最终生效的配置符合预期。
Manifest 是应用与系统之间的静态契约,它不能承载业务逻辑,但所有对系统可见的能力都从这里开始。理解每一个标签的含义,并在项目迭代中保持声明与实际代码同步,是 Android 开发者必须具备的基本功。
Android Manifest应用配置组件声明修改时间:2026-09-26 11:01:05