刚接触Android开发的人,第一次创建项目时通常会被目录结构吓一跳:明明只写了一个页面,工程里却冒出了十几个文件夹和一堆后缀名奇怪的文件。其实Android项目的目录组织是有严格规范的,Google官方对此有明确定义,理解了每个目录的职责之后,你会发现这套结构其实非常清晰。本文按照从外到内的顺序,把一个标准Android工程的目录结构完整梳理一遍。

工程根目录:项目的全局配置都在这里
一个Android工程的最外层,也就是项目的根目录,存放着所有与整体构建相关的文件。以Android Studio默认生成的工程为例,根目录通常包含以下内容:
MyApplication/ ├── app/ // 应用主模块 ├── build/ // 项目构建产物输出目录,自动生成 ├── gradle/ │ └── wrapper/ // Gradle Wrapper 相关文件 ├── .gitignore // Git 忽略规则 ├── build.gradle // 项目级构建脚本 ├── settings.gradle // 声明参与构建的所有模块 ├── gradle.properties // Gradle 全局属性配置 ├── gradlew // Linux/Mac 下的构建脚本 └── gradlew.bat // Windows 下的构建脚本
其中settings.gradle是最容易被新手忽略但非常重要的文件,它决定了哪些模块会参与构建。当你新增一个功能模块,比如添加一个login模块时,必须在这里声明:
include ':app' include ':login' include ':common'
根目录的build.gradle则负责声明整个项目通用的仓库地址和插件依赖。比如你需要在多个模块中使用Kotlin,就可以在这里统一声明Kotlin插件的版本,子模块就不必重复指定了。gradle.properties用于存放构建参数,常见配置如JVM堆内存大小、开启AndroidX支持、并行构建开关等,团队协作时这个文件经常需要调整,否则大型项目编译可能因为内存不足而失败。
另外注意build目录和gradle目录的区别:build是编译输出的临时产物,可以随时删除,一般会加入版本控制忽略列表;而gradle/wrapper下的文件记录了项目使用的Gradle版本,提交代码时必须一并上传,这样其他人拉取代码后才能用完全相同的Gradle版本构建,避免环境不一致带来的诡异问题。
app模块:应用本体的核心目录
app是绝大多数项目的主模块,也是业务代码存放的地方。展开后主要结构如下:
app/ ├── src/ │ ├── main/ │ │ ├── java/ // Java/Kotlin 源代码 │ │ ├── res/ // 资源文件 │ │ ├── assets/ // 原始资源文件 │ │ └── AndroidManifest.xml // 应用清单文件 │ ├── test/ // 单元测试 │ └── androidTest/ // 仪表测试 ├── libs/ // 第三方 jar/aar 依赖 ├── build.gradle // 模块级构建脚本 └── proguard-rules.pro // 混淆规则
src/main/java目录下存放所有源代码,包名结构通常与业务划分对应,比如按功能划分为ui、data、network等子包。Android Studio在视图模式下可能显示为java,即使你用的是Kotlin也一样,这只是历史遗留的目录命名,不必纠结。
res目录是资源的大本营,内部按资源类型分为多个子目录:layout存放布局文件,values存放字符串、颜色、尺寸等可复用的值,drawable存放图片和矢量图形,mipmap存放应用图标,menu存放菜单定义。关键在于命名规则:资源文件名只能包含小写字母、数字和下划线,否则编译直接报错。同时Android支持限定符机制,例如values-zh表示中文环境使用的字符串资源,layout-land表示横屏布局,系统会在运行时根据设备状态自动选择合适的资源,这正是Android多语言和屏幕适配的基础。
assets目录与res的区别值得单独说明:res中的资源会被编译处理并生成资源ID,可以通过R.layout.xxx这样的方式访问;而assets中的文件原封不动打包进APK,不生成任何ID,只能通过AssetManager以文件流的方式读取。因此像预置数据库、本地HTML、字体文件这类不需要资源系统的内容,通常放在assets里。
libs目录用于存放本地的jar包或aar包,比如某些厂商只提供离线SDK时,就需要把对应的aar文件放进libs,并在build.gradle中声明依赖。模块级的build.gradle则是日常打交道最多的文件,应用的包名、版本号、最低SDK版本、第三方依赖、签名配置、混淆开关全部在这里定义:
android {
defaultConfig {
applicationId "com.example.myapplication"
minSdk 24 // 最低支持的系统版本
targetSdk 34 // 目标系统版本
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true // 开启混淆
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}AndroidManifest.xml:应用的身份证
每个Android应用必须有且只有一个清单文件,它向系统声明这个应用的完整信息。具体来说包含四类关键内容:应用的包名与组件注册、权限声明、硬件特性要求以及应用入口配置。
四大组件——Activity、Service、BroadcastReceiver和ContentProvider——都必须在这里注册,没有注册的组件在运行时会直接抛出异常。以Activity为例:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.App">
<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>
</application>
</manifest>uses-permission标签声明权限,比如访问网络、读取存储都需要在此列出,运行时权限还需要在代码中动态申请。带有MAIN和LAUNCHER意图过滤器的Activity就是应用启动时打开的入口页面。需要注意的是,从Android 12开始,凡是会暴露给外部应用的组件都必须显式声明android:exported属性,否则无法通过编译,这是很多老项目升级时踩过的坑。
清单文件在合并时也遵循一定的规则。多模块项目中,每个模块都有自己的Manifest,最终打包时Gradle会把它们合并成一份,组件和权限会叠加,如果出现冲突,构建过程会明确提示冲突来源,此时需要检查各模块是否重复注册了同名组件。
容易被忽视的配置文件与目录
除了主干目录,还有一些细节文件值得了解。proguard-rules.pro存放代码混淆规则,开启混淆后,反射调用的类、序列化的数据模型通常需要在这里添加keep规则,否则运行时会因为类名被改写而崩溃:
-keep class com.example.model.** { *; }
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
}.gitignore文件定义了版本控制要忽略的内容,build目录、本地配置文件、IDE生成的临时文件都应该排除在外。如果发现编译产物被提交到了仓库,多半是忽略规则没有配置到位。
随着项目规模增长,单模块结构会让编译越来越慢,代码边界也越来越模糊。此时可以按功能拆分出多个模块,例如把网络层抽成network模块、公共UI抽成common模块,主工程只保留业务代码。多模块结构的本质就是把app目录的组织方式复制到新模块中,再通过settings.gradle引入、在依赖中使用implementation project(':network')引用即可。掌握单模块的目录结构后,向多模块演进就只是量的变化,没有理解上的障碍了。
Android项目结构gradle配置AndroidManifest修改时间:2026-09-12 08:04:36