Cấu trúc thư mục, file trong một project ứng dụng Android

BinlerdevBinlerdev
8 min read

Giới thiệu

Khi bạn tạo một project Android mới trong Android Studio, hệ thống sẽ tự động tạo ra một cấu trúc thư mục phức tạp với rất nhiều file và folder. Đối với người mới bắt đầu, điều này có thể gây choáng ngợp. Bài viết này sẽ giúp bạn hiểu rõ mục đích của từng thành phần trong project Android.

Tổng quan về cấu trúc project

Khi tạo project mới, Android Studio sẽ tạo ra cấu trúc thư mục như sau:

MyAndroidApp/
├── .gradle/                          # Thư mục cache của Gradle
├── .idea/                            # Cấu hình IDE
├── app/                              # Module chính của ứng dụng
│   ├── build/                        # File build tự động sinh
│   ├── src/                          # Source code
│   │   ├── main/                     # Source code chính
│   │   │   ├── java/                 # Code Kotlin/Java
│   │   │   │   └── com/example/myapp/
│   │   │   │       └── MainActivity.kt
│   │   │   ├── res/                  # Resources (tài nguyên)
│   │   │   │   ├── drawable/         # Hình ảnh, icon
│   │   │   │   ├── layout/           # Layout XML
│   │   │   │   ├── mipmap/           # App icons
│   │   │   │   ├── values/           # Strings, colors, themes
│   │   │   │   └── xml/              # XML config files
│   │   │   └── AndroidManifest.xml   # Manifest file
│   │   ├── test/                     # Unit tests
│   │   └── androidTest/              # Instrumentation tests
│   ├── build.gradle                  # Build config cho app module
│   └── proguard-rules.pro            # ProGuard rules
├── gradle/                           # Gradle wrapper
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── build.gradle                      # Build config cho project
├── gradle.properties                 # Gradle properties
├── gradlew                           # Gradle wrapper (Unix)
├── gradlew.bat                       # Gradle wrapper (Windows)
├── local.properties                  # Local SDK path
└── settings.gradle                   # Project settings

Chi tiết từng thành phần

1. Thư mục gốc của project

.gradle/

  • Mục đích: Chứa cache và temporary files của Gradle build system

  • Lưu ý: Không nên commit vào Git, tự động tạo lại khi build

  • Tài liệu: Gradle Build Cache

.idea/

  • Mục đích: Chứa cấu hình IDE của IntelliJ IDEA/Android Studio

  • Bao gồm: Settings, code styles, run configurations, workspace

  • Lưu ý: Một số file có thể commit, một số không nên

  • Tài liệu: IntelliJ IDEA Project Structure

gradle/

  • Mục đích: Chứa Gradle Wrapper

  • Lợi ích: Đảm bảo tất cả developers sử dụng cùng phiên bản Gradle

  • Tài liệu: Gradle Wrapper

2. Module app - Thư mục chính

app/src/main/java/

Chứa toàn bộ source code Kotlin/Java của ứng dụng.

Cấu trúc package:

com/example/myapp/
├── MainActivity.kt          # Activity chính
├── adapters/               # RecyclerView Adapters
├── fragments/              # Fragments
├── models/                 # Data models
├── utils/                  # Utility classes
└── viewmodels/             # ViewModels (MVVM)

MainActivity.kt - File quan trọng nhất:

package com.example.myapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Tài liệu: Application Components

app/src/main/res/ - Thư mục tài nguyên

res/layout/

Chứa các file XML định nghĩa giao diện người dùng.

activity_main.xml - Layout chính:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Tài liệu: Layouts

res/values/

Chứa các giá trị constants như strings, colors, styles.

strings.xml:

<resources>
    <string name="app_name">My Android App</string>
    <string name="hello_world">Hello World!</string>
    <string name="button_text">Click Me</string>
</resources>

colors.xml:

<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
</resources>

themes.xml:

<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Theme.MyAndroidApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Customize your theme here. -->
    </style>
</resources>

Tài liệu: String Resources, Color Resources

res/drawable/

Chứa hình ảnh, icons, và drawable resources.

Các định dạng hỗ trợ:

  • PNG (khuyến nghị cho photos)

  • JPG (cho photos có nhiều màu)

  • WebP (tối ưu size)

  • Vector Drawable (cho icons)

Ví dụ Vector Drawable (ic_launcher_foreground.xml):

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path android:fillColor="#3DDC84"
          android:pathData="M0,0h108v108h-108z"/>
    <path android:fillColor="#00000000"
          android:pathData="M9,0L9,108L0,108L0,0L9,0z"/>
</vector>

Tài liệu: Drawable Resources

res/mipmap/

Chứa app icons với các độ phân giải khác nhau.

Cấu trúc thư mục:

mipmap-mdpi/     # 48x48 dp (1x)
mipmap-hdpi/     # 72x72 dp (1.5x)
mipmap-xhdpi/    # 96x96 dp (2x)
mipmap-xxhdpi/   # 144x144 dp (3x)
mipmap-xxxhdpi/  # 192x192 dp (4x)

Tài liệu: App Icons

app/src/main/AndroidManifest.xml

File quan trọng nhất, khai báo thông tin về ứng dụng.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">

    <!-- Permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.MyAndroidApp">

        <!-- Main Activity -->
        <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>

        <!-- Other Activities -->
        <activity android:name=".SecondActivity" />

        <!-- Services -->
        <service android:name=".MyService" />

        <!-- Receivers -->
        <receiver android:name=".MyReceiver" />

    </application>

</manifest>

Các thành phần chính:

  • package: Tên package unique của app

  • uses-permission: Khai báo quyền cần thiết

  • application: Cấu hình ứng dụng

  • activity: Khai báo các Activities

  • service: Khai báo các Services

  • receiver: Khai báo các Broadcast Receivers

Tài liệu: App Manifest

3. Thư mục test

app/src/test/

Chứa unit tests (chạy trên JVM).

Ví dụ ExampleUnitTest.kt:

import org.junit.Test
import org.junit.Assert.*

class ExampleUnitTest {
    @Test
    fun addition_isCorrect() {
        assertEquals(4, 2 + 2)
    }
}

app/src/androidTest/

Chứa instrumentation tests (chạy trên device/emulator).

Ví dụ ExampleInstrumentedTest.kt:

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*

@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Test
    fun useAppContext() {
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        assertEquals("com.example.myapp", appContext.packageName)
    }
}

Tài liệu: Testing

4. Gradle Files - Cấu hình build

build.gradle (Project level)

Cấu hình cho toàn bộ project.

buildscript {
    ext.kotlin_version = "1.8.10"
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.4.2"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

app/build.gradle (Module level)

Cấu hình cho app module.

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    namespace 'com.example.myapp'
    compileSdk 33

    defaultConfig {
        applicationId "com.example.myapp"
        minSdk 21
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation 'androidx.core:core-ktx:1.9.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.8.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

Các thành phần quan trọng:

  • compileSdk: Phiên bản Android SDK để compile

  • minSdk: Phiên bản Android tối thiểu hỗ trợ

  • targetSdk: Phiên bản Android target

  • applicationId: ID unique của app trên Play Store

  • versionCode: Số version cho internal tracking

  • versionName: Tên version hiển thị cho user

Tài liệu: Configure your build

gradle.properties

Cấu hình properties cho Gradle.

# Project-wide Gradle settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.caching=true

# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
android.useAndroidX=true

# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official

# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

settings.gradle

Cấu hình modules trong project.

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "My Android App"
include ':app'

Tài liệu: Gradle Settings

5. Các file khác

local.properties

Chứa đường dẫn đến Android SDK (không commit vào Git).

sdk.dir=/Users/username/Library/Android/sdk

proguard-rules.pro

Cấu hình ProGuard để obfuscate code khi build release.

# Add project specific ProGuard rules here.
-keep class com.example.myapp.** { *; }
-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}

Tài liệu: Shrink, obfuscate, and optimize your app

gradlewgradlew.bat

Gradle wrapper scripts cho Unix và Windows.

# Chạy trên Unix/macOS/Linux
./gradlew assembleDebug

# Chạy trên Windows
gradlew.bat assembleDebug

Workflow cơ bản

1. Tạo giao diện

  1. Mở res/layout/activity_main.xml

  2. Thêm các View components

  3. Thiết lập constraints/layout

2. Viết logic

  1. Mở MainActivity.kt

  2. Thêm code xử lý trong onCreate()

  3. Implement event listeners

3. Thêm resources

  1. Thêm strings vào res/values/strings.xml

  2. Thêm colors vào res/values/colors.xml

  3. Thêm images vào res/drawable/

4. Cấu hình permissions

  1. Thêm permissions vào AndroidManifest.xml

  2. Implement runtime permissions nếu cần

5. Test và debug

  1. Chạy app trên emulator/device

  2. Sử dụng Logcat để debug

  3. Viết unit tests nếu cần

Best Practices

1. Tổ chức code

  • Sử dụng packages để nhóm các class related

  • Đặt tên file và class theo convention

  • Tách biệt UI code và business logic

2. Resources management

  • Sử dụng string resources thay vì hardcode text

  • Tối ưu images và sử dụng vector drawable

  • Hỗ trợ multiple screen densities

3. Performance

  • Tránh memory leaks

  • Sử dụng ViewBinding/DataBinding

  • Optimize layouts

4. Security

  • Không commit sensitive data vào Git

  • Sử dụng ProGuard cho release builds

  • Validate user inputs

Tài liệu tham khảo chính thức

Android Developer Documentation

Cấu trúc project

Components

Resources

Build System

Testing

Kotlin

Kết luận

Hiểu rõ cấu trúc project Android là bước đầu tiên quan trọng để trở thành một Android developer. Mỗi file và thư mục đều có vai trò riêng, và việc tổ chức code tốt sẽ giúp bạn maintain và scale ứng dụng dễ dàng hơn.

Hãy bắt đầu với việc tạo một project đơn giản và khám phá từng thành phần. Đừng ngần ngại tham khảo documentation chính thức từ Google để hiểu sâu hơn về từng phần.

0
Subscribe to my newsletter

Read articles from Binlerdev directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Binlerdev
Binlerdev