Android 項目根目錄概覽
MyApplication/
├── .gradle/ # Gradle 緩存/守護進程狀態 (忽略)
├── .idea/ # IDEA 配置 (忽略)
├── app/ # 主模塊 (可有多模塊: library, feature, dynamic-feature)
├── gradle/
│ └── wrapper/ # Gradle Wrapper (gradlew, gradle-wrapper.jar, properties)
├── build.gradle(.kts) # 項目級構建腳本 (全局配置、插件版本、倉庫)
├── settings.gradle(.kts) # 項目包含模塊聲明
├── gradle.properties # 全局屬性 (JVM 參數、版本號、簽名密鑰)
├── local.properties # 本機 SDK/NDK 路徑 (不提交版本控制)
└── README.md
核心模塊結構 (app/)
app/
├── build/ # 構建產物 (忽略,由 Gradle 生成)
│ ├── generated/ # 生成代碼 (R.java, BuildConfig, ViewBinding, DataBinding, KSP/KAPT)
│ ├── intermediates/ # 中間產物 (編譯類文件、合併資源、Dex)
│ ├── outputs/ # 最終產物 (APK/AAB, Mapping.txt, ProGuard 映射)
│ └── reports/ # 檢查報告 (Lint, Detekt, Test Coverage)
├── libs/ # 本地依賴 Jar/Aar (少用,優先 Maven 遠程)
├── src/
│ ├── main/ # 主源碼集 (生產代碼)
│ │ ├── java/ # Java/Kotlin 源碼 (包結構)
│ │ │ └── com/example/myapp/
│ │ ├── res/ # 資源文件
│ │ │ ├── drawable/ # 圖片、Shape、Selector (按密度分級: mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi)
│ │ │ ├── layout/ # XML 布局
│ │ │ ├── values/ # 字符串、顏色、尺寸、主題、樣式、整數、布爾、數組
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── themes.xml
│ │ │ │ └── attrs.xml (自定義屬性)
│ │ │ ├── menu/ # 選單 XML
│ │ │ ├── xml/ # 配置 XML (preferences, searchable, backup rules)
│ │ │ ├── raw/ # 原始文件 (音頻、視頻、JSON、證書) - 保持原始文件名
│ │ │ ├── assets/ # 原始資產 (字體、HTML、數據庫) - 保持目錄結構,需 AssetManager 讀取
│ │ │ ├── mipmap/ # 啟動圖標 (唯一用途,按密度分級)
│ │ │ └── font/ # 字體資源 (XML 字體族)
│ │ ├── AndroidManifest.xml # 清單文件 (組件聲明、權限、應用元數據)
│ │ └── cpp/ # NDK C/C++ 源碼 (可選)
│ ├── test/ # 單元測試源碼集 (JVM 運行,無 Android 依賴)
│ │ └── java/com/example/myapp/
│ ├── androidTest/ # 儀器測試源碼集 (設備/模擬器運行,有 Android 上下文)
│ │ └── java/com/example/myapp/
│ ├── debug/ # Debug 變體專用代碼/資源 (覆蓋 main)
│ │ ├── java/...
│ │ └── res/...
│ ├── release/ # Release 變體專用 (混淆規則、簽名配置、去除日誌)
│ │ └── ...
│ └── [flavor]/ # 產品風味專用源碼集 (如 free, paid, china, global)
│ └── ...
├── build.gradle(.kts) # 模塊級構建腳本 (依賴、編譯選項、簽名、變體)
├── proguard-rules.pro # R8/ProGuard 混淆規則
└── .gitignore
關鍵文件深度解析
1. build.gradle.kts (模塊級) - 構建核心
plugins {
id("com.android.application") // 或 library
id("org.jetbrains.kotlin.android")
id("kotlin-kapt") // 或 ksp
}
android {
namespace = "com.example.myapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// 多Dex、VectorDrawable、Java 8 支持
multiDexEnabled = true
}
buildTypes {
release {
isMinifyEnabled = true // 啟用 R8 混淆壓縮
isShrinkResources = true // 移除無用資源
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signingConfigs.release
}
debug {
isDebuggable = true
isMinifyEnabled = false
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
}
}
flavorDimensions = "version"
productFlavors {
create("free") { dimension = "version"; applicationIdSuffix = ".free" }
create("paid") { dimension = "version"; applicationIdSuffix = ".paid" }
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions { jvmTarget = "17" }
buildFeatures {
viewBinding = true
dataBinding = true
compose = true
}
}
dependencies {
// AndroidX 核心
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.activity:activity-compose:1.8.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
// Material Design
implementation("com.google.android.material:material:1.11.0")
// Coroutines & Flow
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
// Room Database
implementation("androidx.room:room-runtime:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")
// Retrofit + OkHttp
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-moshi:2.9.0")
// Coil 圖片加載
implementation("io.coil-kt:coil-compose:2.5.0")
// 測試
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}
2. AndroidManifest.xml - 應用身份證
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.myapp"> <!-- package 現僅作為 R.java 生成包名,applicationId 以 build.gradle 為準 -->
<!-- 權限聲明 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<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"
android:theme="@style/Theme.MyApp"
android:networkSecurityConfig="@xml/network_security_config"
android:dataExtractionRules="@xml/data_extraction_rules"
android:backupRules="@xml/backup_rules">
<!-- 入口 Activity -->
<activity
android:name=".MainActivity"
android:exported="true" <!-- Android 12+ 必須顯式聲明 -->
android:label="@string/app_name"
android:theme="@style/Theme.MyApp.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 其他組件 -->
<service android:name=".DownloadService" android:foregroundServiceType="dataSync" />
<receiver android:name=".BootReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false" />
</application>
</manifest>
構建產物輸出路徑
| 產物類型 | 路徑 | 用途 |
| Debug APK | app/build/outputs/apk/debug/app-debug.apk | 開發調試安裝 |
| Release APK | app/build/outputs/apk/release/app-release.apk | 發布分發 (需簽名) |
| Release AAB | app/build/outputs/bundle/release/app-release.aab | Google Play 上傳格式 (Dynamic Delivery) |
| Mapping 文件 | app/build/outputs/mapping/release/mapping.txt | 崩潰堆疊反混淆、Bug 定位 |
| Lint 報告 | app/build/reports/lint-results.html | 代碼質量、性能、安全掃描 |
多模塊架構最佳實踐
settings.gradle.kts:
include(":app")
include(":core:common") // 純 Kotlin/Java 庫 (無 Android 依賴)
include(":core:network") // 網絡層 (Retrofit, OkHttp 封裝)
include(":core:database") // 數據層 (Room, DataStore 封裝)
include(":feature:home") // 功能模塊 (首頁)
include(":feature:profile") // 功能模塊 (個人中心)
include(":feature:payment") // 動態功能模塊 (動態分發)
include(":ui:design-system") // UI 組件庫 (Compose/View 組件、主題、資源)
- core:* 穩定、低變更、被多模塊依賴
- feature:* 業務邏輯、可獨立編譯測試、支援動態分發
- ui:* 設計系統、統一視覺語言
- 依賴方向:
app → feature → core → ui (單向,禁止循環)
常見配置文件對照表
| 文件 | 作用域 | 典型內容 |
gradle.properties | 全局 | 版本號、JVM 參數、簽名密鑰 (加密存儲) |
local.properties | 本機 | sdk.dir, ndk.dir, cmake.dir |
proguard-rules.pro | 模塊 | 保留規則、移除日誌、第三方庫適配 |
gradle/wrapper/gradle-wrapper.properties | 全局 | Gradle 版本、下載 URL |
總結
Android 項目目錄結構是 Gradle 約定大於配置的體現。理解 src/main (主代碼)、src/test (單測)、src/androidTest (儀器測)、buildTypes (構建類型)、productFlavors (產品風味)、build/ (產物輸出) 的分工,能讓你精準控制構建流程、快速定位問題、優雅實現多模塊架構。現代項目建議:Kotlin DSL (build.gradle.kts)、Version Catalogs (libs.versions.toml)、KSP 替代 KAPT、Compose 替代 XML、模塊化解耦。