1. 项目环境搭建

1.1 环境要求与工具准备

在开始构建多媒体播放 UI 之前,需要确保开发环境满足以下最低要求。使用不匹配的版本可能导致 Gradle 同步失败或 Compose 编译错误。

组件最低版本推荐版本说明
Android StudioHedgehog (2023.1.1)Iguana (2023.2.1)必须包含 Compose 模板
JDK1717 LTSAGP 8.x 强制要求
Gradle8.28.5与 AGP 版本配对
Android Gradle Plugin8.1.08.2.2需在项目级配置
Compose BOM2024.01.002024.02.00统一管理 Compose 版本
minSdk21 (Android 5.0)26 (Android 8.0)Media3 最低要求 21
targetSdk3334适配最新平台
版本配对原则:AGP 版本与 Gradle 版本存在严格依赖关系。AGP 8.2.x 要求 Gradle ≥ 8.2,AGP 8.1.x 要求 Gradle ≥ 8.0。使用 gradle-wrapper.properties 明确指定 Gradle 版本,避免自动升级导致不兼容。

1.2 创建 Compose 项目

通过 Android Studio 的项目向导快速生成 Compose 工程骨架,这是最可靠的方式,能自动生成正确的 Compose 编译器配置。

  1. 启动 Android Studio,点击 New Project。
  2. 选择模板 Empty Compose Activity(位于 Phone 和 Tablet 分类下)。
  3. 填写项目信息:Name 为 MediaPlayerUI,Package name 为 com.example.mediaplayerui,Language 选择 Kotlin。
  4. Minimum SDK 下拉选择 API 21: Android 5.0 (Lollipop)——这是 Media3 库支持的最低 API 级别。
  5. 点击 Finish,Android Studio 会自动生成项目结构和初始代码。

生成后的项目目录结构如下所示:

MediaPlayerUI/
├── app/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/com/example/mediaplayerui/
│       │   │   └── MainActivity.kt
│       │   └── res/
│       └── test/
├── build.gradle.kts                 # 项目级构建脚本
├── settings.gradle.kts
└── gradle/
    └── libs.versions.toml           # 版本目录(可选)
避免手动创建:不推荐从空白项目手动添加 Compose 配置。项目向导会自动设置 composeOptions 中的 kotlinCompilerExtensionVersion,手动配置极易出现编译器版本不匹配导致的 @Composable invocations can only happen from the context of a @Composable function 错误。

1.3 配置 Gradle 构建脚本

项目创建后,需要校准 项目级 和 模块级 的 build.gradle.kts,确保 Compose 编译器和 Media3 依赖能够正确解析。

1.3.1 项目级 build.gradle.kts

位于项目根目录,主要声明 AGP 和 Kotlin 插件版本。以下为典型配置:

// 项目根目录 /build.gradle.kts
plugins {
    id("com.android.application") version "8.2.2" apply false
    id("org.jetbrains.kotlin.android") version "1.9.22" apply false
}

1.3.2 模块级 build.gradle.kts

位于 app/ 目录,包含 Android 配置、Compose 启用和所有依赖项。这是整个环境搭建的核心文件。

// app/build.gradle.kts
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.example.mediaplayerui"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.mediaplayerui"
        minSdk = 21
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"
    }

    buildFeatures {
        compose = true
    }

    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.10"
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = "17"
    }
}

dependencies {
    // Compose BOM — 统一管理所有 Compose 组件版本
    val composeBom = platform("androidx.compose:compose-bom:2024.02.00")
    implementation(composeBom)

    // Compose 核心组件
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
    implementation("androidx.activity:activity-compose:1.8.2")

    // Media3 依赖(后续章节详细使用)
    implementation("androidx.media3:media3-exoplayer:1.2.1")
    implementation("androidx.media3:media3-ui:1.2.1")
    implementation("androidx.media3:media3-common:1.2.1")

    // 调试工具
    debugImplementation("androidx.compose.ui:ui-tooling")
    debugImplementation("androidx.compose.ui:ui-test-manifest")
}

1.3.3 settings.gradle.kts 与 gradle.properties

settings.gradle.kts 负责声明项目模块,确保 app 模块被包含:

// settings.gradle.kts
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolution {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "MediaPlayerUI"
include(":app")

gradle.properties 中至少需要开启 Compose 增量编译和 AndroidX 支持:

android.useAndroidX=true
kotlin.code.style=official
android.nonTransitiveRClass=true
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
Kotlin 编译器扩展版本对齐:Compose 编译器扩展版本必须与 Kotlin 版本严格对应。Kotlin 1.9.22 对应 Compose 编译器扩展 1.5.10。版本错配会导致 Incompatible compiler version 构建失败。查阅 Compose-Kotlin 兼容性映射表 确认匹配关系。

1.4 引入 Media3 依赖

Media3 是 Android 多媒体框架的新一代库,统一了 ExoPlayer 和 MediaSession 的实现。在 app/build.gradle.kts 的 dependencies 块中已添加了三个核心 artifact,以下说明每个模块的作用:

Artifact功能必要性
media3-exoplayer核心播放引擎,支持 DASH/HLS/SS 流媒体和本地文件必须
media3-ui提供 PlayerView、TimeBar 等开箱即用的 UI 组件强烈推荐
media3-common包含 Player 接口、MediaItem、监听器等公共定义必须(被 exoplayer 传递依赖)
media3-session支持 MediaSession 和 MediaController,用于后台播放和媒体通知按需

添加依赖后,务必点击 Android Studio 工具栏中的 Sync Now 或执行 Gradle 同步命令:

./gradlew build --refresh-dependencies

若同步成功,External Libraries 中会出现 androidx.media3:media3-exoplayer:1.2.1 等条目。如果遇到 Failed to resolve 错误,请检查 settings.gradle.kts 是否包含了 google() 仓库。

1.5 设置 minSdk 版本

Media3 库编译要求 minSdk ≥ 21,但实际运行中存在两个重要考量:

  • 功能完整性:API 26 (Android 8.0) 引入了 MediaCodec 异步编解码和 MediaPlayer 的完整 DRM 支持。若 minSdk < 26,部分高级流媒体功能(如 ClearKey DRM)需要额外兼容代码。
  • Compose 性能:Compose 在 API 26+ 上支持硬件加速渲染和更高效的 LayoutNode 测量。推荐将 minSdk 设为 26 以获得流畅的动画和列表滚动体验。

修改 app/build.gradle.kts 中的 minSdk 值即可:

defaultConfig {
    minSdk = 26   // 从 21 改为 26
}

更改后重新同步 Gradle。若项目中使用到了仅 API 26+ 的 API(如 MediaCodec.CryptoInfo.setPattern),请用 @RequiresApi(Build.VERSION_CODES.O) 注解标记或添加 Build.VERSION.SDK_INT 运行时判断。

兼容性策略:如果必须支持 API 21–25 的设备,仍可将 minSdk 保持为 21,但需要对 media3-ui 中的 PlayerView 做 Surface 兼容性测试——部分旧设备不支持 SurfaceView 的透明叠加层。建议在 AndroidManifest.xml 中为 API 26 以下机型声明 android:hardwareAccelerated="false" 作为兜底。

1.6 验证项目配置

完成上述配置后,执行完整的构建与安装流程,确认环境就绪:

  1. Gradle 同步:点击 File → Sync Project with Gradle Files,观察 Build Output 面板无红色错误。
  2. 编译检查:运行 ./gradlew assembleDebug,终端输出 BUILD SUCCESSFUL in xx s。
  3. 运行空 Activity:连接模拟器 (API 26+) 或真机,点击 Run。应用应显示 "Hello Android!" 或 Compose 默认文本,无崩溃或 ANR。
  4. 验证 Media3 可达性:在 MainActivity.kt 中临时输入 import androidx.media3.common.MediaItem,IDE 无红色波浪线。

至此,项目环境搭建完成,可以进入下一阶段——多媒体播放 UI 的具体实现。

项目环境搭建流程 环境搭建完整流程图 ① 创建 Compose 项目 ② 配置项目级 Gradle ③ 配置模块级 Gradle ④ 引入 Media3 依赖 ⑤ 设置 minSdk 版本 ⑥ 同步并验证 💡 推荐 minSdk ≥ 26 Compose 性能更优 Gradle 配置阶段 依赖与 SDK 配置阶段