Skip to content

在 Android 开发中,AndroidManifest.xml 是应用的核心配置文件,定义了应用的基本信息、组件声明、权限请求等关键内容。以下是需要掌握的核心知识:


一、AndroidManifest 的作用

  1. 声明应用组件
    • Activity、Service、BroadcastReceiver、ContentProvider 等组件的注册。
  2. 权限管理
    • 声明应用需要的权限(如相机、网络访问)。
  3. 应用元数据
    • 应用名称、图标、版本号、支持的 Android 版本等。
  4. 入口点定义
    • 指定应用启动时的主 Activity。
  5. 特殊功能配置
    • 处理深链接(Deep Link)、多窗口模式、硬件需求等。

二、文件基础结构

xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.myapp"> <!-- 应用包名(与 build.gradle 中的 applicationId 可能不同) -->

    <!-- 权限声明 -->
    <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"
        tools:targetApi="31">

        <!-- 主 Activity(入口点) -->
        <activity
            android:name=".MainActivity"
            android:exported="true"> <!-- Android 12+ 必须显式声明 exported -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- 其他 Activity -->
        <activity
            android:name=".SecondActivity"
            android:label="Second Screen"
            android:exported="false" />

        <!-- Service 示例 -->
        <service android:name=".MyService" />

        <!-- BroadcastReceiver 示例 -->
        <receiver android:name=".MyBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

    </application>
</manifest>

三、关键配置详解

1. 权限声明

  • 普通权限(自动授予):
    xml
    <uses-permission android:name="android.permission.INTERNET" />
  • 危险权限(需运行时请求):
    xml
    <uses-permission android:name="android.permission.CAMERA" />
    在 Kotlin 中动态请求:
    kotlin
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CODE)
    }

2. Activity 配置

  • 基本属性
    xml
    <activity
        android:name=".MainActivity"       <!-- 类名(相对于包名) -->
        android:label="Home"               <!-- 界面标题 -->
        android:screenOrientation="portrait" <!-- 强制竖屏 -->
        android:exported="true"            <!-- 是否允许其他应用启动 -->
        android:launchMode="singleTop" />  <!-- 启动模式 -->
  • Intent Filter(定义 Activity 的响应场景):
    xml
    <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="https" android:host="example.com" />
    </intent-filter>

3. Application 标签

  • 全局配置
    xml
    <application
        android:name=".MyApplication"      <!-- 自定义 Application 类 -->
        android:icon="@mipmap/ic_launcher" <!-- 应用图标 -->
        android:label="@string/app_name"   <!-- 应用名称 -->
        android:theme="@style/AppTheme"    <!-- 全局主题 -->
        android:usesCleartextTraffic="true"><!-- 允许 HTTP 明文流量 -->

四、高级配置示例

1. 适配新版本 Android

  • 指定 targetSdkVersion 兼容性:
    xml
    <uses-sdk
        android:minSdkVersion="21"
        android:targetSdkVersion="34" />

2. 处理配置变更

  • 禁止 Activity 在旋转屏幕时重建:
    xml
    <activity
        android:name=".CameraActivity"
        android:configChanges="orientation|screenSize|keyboardHidden" />

3. 多进程配置

  • 为 Service 指定独立进程:
    xml
    <service
        android:name=".BackgroundService"
        android:process=":remote" />

五、与 Kotlin 代码的交互

1. 获取 Meta-Data 信息

在 Manifest 中定义:

xml
<meta-data
    android:name="com.example.API_KEY"
    android:value="your_api_key_here" />

在 Kotlin 中读取:

kotlin
val appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)
val apiKey = appInfo.metaData.getString("com.example.API_KEY")

2. 动态注册组件

  • 代码中注册 BroadcastReceiver:
    kotlin
    val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
    registerReceiver(networkReceiver, filter)

六、注意事项

  1. Android 12+ 的 exported 属性
    所有包含 <intent-filter> 的组件必须显式声明 android:exported="true|false"

  2. 权限分组
    请求危险权限时,需处理用户拒绝的情况(参考运行时权限最佳实践)。

  3. 包名管理
    package 属性用于生成 R 类,而 build.gradle 中的 applicationId 是应用唯一标识,二者可不同。

  4. ProGuard/R8 混淆
    需在 proguard-rules.pro 中保留 Manifest 中声明的组件:

    -keep public class * extends android.app.Activity
    -keep public class * extends android.app.Service

通过合理配置 AndroidManifest.xml,你可以确保应用功能正确运行并适配不同设备。

Activity、布局文件和AndroidManifest之间的关系

在 Android 开发中,Activity布局文件AndroidManifest.xml 是三个紧密关联的核心概念,它们共同协作完成应用的界面展示和功能逻辑。以下是它们之间的关系解析:


一、角色分工

组件作用类比
Activity控制用户界面逻辑的「控制器」,负责处理用户交互、数据加载和生命周期管理。餐厅的「服务员」
布局文件定义用户界面的「视图模板」,描述屏幕上显示哪些组件(按钮、文本框等)及其排列方式。餐厅的「菜单和餐桌布局」
AndroidManifest应用的「全局配置中心」,声明所有组件(如 Activity)的存在和权限等元信息。餐厅的「营业执照和经营许可」

二、具体关系解析

1. Activity 与布局文件

  • 绑定关系
    Activity 通过 setContentView(R.layout.xxx) 加载布局文件,将 XML 定义的 UI 渲染到屏幕上:
    kotlin
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main) // 绑定布局文件
        }
    }
  • 动态操作
    Activity 通过 findViewByIdView Binding 获取布局中的视图对象,并控制其行为:
    kotlin
    // 传统方式
    val button = findViewById<Button>(R.id.btn_submit)
    button.setOnClickListener { /* 处理点击事件 */ }
    
    // View Binding 方式
    private lateinit var binding: ActivityMainBinding
    binding = ActivityMainBinding.inflate(layoutInflater)
    binding.btnSubmit.text = "更新文本"

2. Activity 与 AndroidManifest

  • 注册关系
    所有 Activity 必须AndroidManifest.xml 中声明,否则系统无法识别和启动它:
    xml
    <application>
        <activity
            android:name=".MainActivity"       <!-- 类名(相对于包名) -->
            android:label="主界面"             <!-- 界面标题 -->
            android:exported="true">           <!-- 是否允许外部应用启动 -->
            <intent-filter>                    <!-- 定义启动入口 -->
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
  • 启动规则
    • 通过 Intent 启动其他 Activity 时,目标 Activity 必须在 Manifest 中注册。
    • android:exported 属性控制是否允许其他应用调用该 Activity。

3. 布局文件与 AndroidManifest

  • 间接关联
    布局文件本身不直接与 Manifest 交互,但通过 Activity 间接关联:
    • Manifest 声明 Activity 的存在和属性。
    • Activity 负责加载布局文件并渲染 UI。

三、协作流程示例

以启动一个 Activity 为例,三者协作过程如下:

  1. 用户点击应用图标

    • Manifest 中声明了 MainActivity<intent-filter>,系统识别其为入口 Activity。
  2. 系统创建 MainActivity 实例

    • 调用 onCreate() 方法,执行 setContentView(R.layout.activity_main) 加载布局文件。
  3. 渲染界面

    • 布局文件 activity_main.xml 定义的 UI 被解析并显示在屏幕上。
  4. 用户交互

    • Activity 通过代码操作布局中的视图(如按钮点击事件)。
  5. 跳转到其他 Activity

    • 通过 Intent 启动 SecondActivity,Manifest 必须已注册该 Activity。

四、关键依赖总结

依赖方向说明
Activity → 布局文件Activity 依赖布局文件定义界面结构。
Activity → ManifestActivity 必须在 Manifest 中注册才能被系统识别。
布局文件 → Activity布局文件中的视图通过 Activity 的代码实现动态逻辑(如点击事件、数据加载)。
Manifest → 系统Manifest 向 Android 系统声明应用的组件和权限,是应用运行的「许可证」。

五、常见问题

1. 如果忘记在 Manifest 中注册 Activity 会怎样?

  • 尝试启动该 Activity 时会抛出 ActivityNotFoundException,应用崩溃。

2. 一个 Activity 可以绑定多个布局文件吗?

  • 可以!通过代码动态切换(如横竖屏适配):
    kotlin
    override fun onCreate(savedInstanceState: Bundle?) {
        if (isLandscape) {
            setContentView(R.layout.activity_main_land)
        } else {
            setContentView(R.layout.activity_main_port)
        }
    }

3. 布局文件能否被多个 Activity 共享?

  • 可以,但通常不推荐。更好的做法是通过 Fragment 或自定义 View 实现复用。

六、最佳实践

  • 模块化:为每个 Activity 创建独立的布局文件,命名清晰(如 activity_main.xml)。
  • View Binding:替代 findViewById,避免空指针异常,提升代码可读性。
  • Manifest 最小化:只声明必要的权限和组件,减少安全风险。

掌握三者关系是 Android 开发的基础,后续可深入学习 FragmentViewModelNavigation 等高级主题。