How I organize Android project structure

In my recent project Material Unit Converter , I have a chance to try out various interesting things like RxJava, MVP, Clean Architecture, …

I will have a post about my experiences with all those trending in other day, but today I want to show you my Android project structure that helps me a lot in managing my codebase.

I. Sensitive data

There are always some sensitive data in your project. Whether it be keystore’s password or third-party API secret key, you want to keep it out of version control system. You can put it in file of your project like below:

KEYSTORE_PASSWORD=<your keystore's password>
KEYSTORE_FILE=<your keystore file>
KEYSTORE_ALIAS=<your keystore's alias>

Later you can use those properties in build.gradle file:

signingConfigs {
release {
storeFile file(KEYSTORE_FILE)

Of course, you need to make sure not committing this file to VCS. But if you are lazy like me, you can put all those properties to file in GRADLE_HOME folder.


To manage all my project’s dependencies, I put it in a library.gradle file:

ext.version = [
support : "23.2.1",
rxjava : "1.1.0",
rxandroid : "1.1.0",

// rest of libraries

def version = ext.version;

ext.library = [
support_compat :
support_design : "${}",
rxjava :
rxandroid :
    // rest of libraries

The file is stored in buildsystem folder of the project.

Then in build.gradle file:

apply from: "$rootProject.projectDir/buildsystem/library.gradle"
def library = ext.library;
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "${library.support_compat}"
compile "${library.support_design}"
compile "${library.rxjava}"
compile "${library.rxandroid}"
    // rest of dependencies

III. Configuration

Like dependencies, I use config.gradle file to store all project configurations.

ext.configuration = [
applicationId : <your app package name>,
versionMajor : 1,
versionMinor : 0,
versionPatch : 2,
versionClassifier : "",
minimumSdkVersion : 14,
compileSdkVersion : 23,
targetSdkVersion : 23,
buildToolsVersion : "23.0.2"

def configuration = ext.configuration;

ext.buildVersionCode = {
return configuration.minimumSdkVersion * 10000000 + configuration.versionMajor * 10000 + configuration.versionMinor * 100 + configuration.versionPatch

ext.buildVersionName = {
String versionName = ext.buildVersionNameWithoutClassifier();
if (configuration.versionClassifier != null && !configuration.versionClassifier.isEmpty()) {
versionName = versionName + "-" + configuration.versionClassifier
return versionName;

You can see that I create buildVersionCode function to generate version code with first 2 digits for minimum SDK version, 1 digit for reverse, then follow with major, minor and patch number, each has 2 digits. For version name, I use format “ major.minor.patch-Classifier”.

Now we can use it in build.gradle file:

apply from: "$rootProject.projectDir/buildsystem/config.gradle"
def configuration = ext.configuration;

android {
compileSdkVersion configuration.compileSdkVersion
buildToolsVersion configuration.buildToolsVersion

defaultConfig {
applicationId configuration.applicationId
minSdkVersion configuration.minimumSdkVersion
targetSdkVersion configuration.targetSdkVersion
versionCode buildVersionCode()
versionName buildVersionName()

IV. Source code packages

Here is my packages structure:

Each data, domain, repository package contains classes of a Clean Architecture’s layer.

common package contains some utility classes. dependency package contains classes that are used to provide dependency injection (Dagger).

Each app’s feature will have it own child package in feature package. It should be the presentation layer of Clean Architecture.

And the last, unitconverter package contains classes that depend on Android framework like Application, Activity, View.

V. Test source folder

I separate test codes to multi-source folders like below:

android {
sourceSets {
// Common code for all tests 'src/commonTests/java' 'src/commonTests/java'

// Unit tests 'src/unitTests/java'

// Integration tests 'src/integrationTests/java'

// Unit tests for debug build variant 'src/debugUnitTests/java'

// Unit tests for release build variant 'src/releaseUnitTests/java'

// Functional tests 'src/functionalTests/java'

You can see we have commonTests source folder for any common class used in test. Each type of test is stored in different source folder, and each build variant also has it own test source folder.

VI. Conclusion

With this structure, my project has become more manageable. In future, I will update this post if I find out way to improve it.