Ultimate Android App Project Structure

Design without code is just a daydream. Code without design is a nightmare.

Although we all know basic Android project structure but often question comes in mind what should be the best code structure that we can use in almost all our projects to make our code more structured, reusable and manageable.

This section describes the complete modern code structure. We identified their are two main code components that can be managed or structured.

  1. Organizing Gradle files
  2. Organizing Source code Package structure

Let’s discuss first about how can we manage gradles files among project and modules. Below image describes the complete gradle structure of a project.

Let’s discuss role of each file and how it should be used.

Project level Gradle files:

  • build.gradle (Project level): Project level build.gradle file contains all the gradle configurations and task that can be used globally in whole project.
  • keystore.properties :This file contains keystore related configuration that can be used in app level build.gradle file to create signing configs. Make sure you are not committing this file and .jks file in VCS for security reasons.

Let’s see how it is used in app level build.gradle file. First you need to define this file, load properties of this file then only you can use properties of this file.

Below changes will make your project to create signed release apk without using explicit ‘Generate signed apk’option.

  • settings.gradle — This file is used to include the available modules. Our project has only one module ‘app’ here.
  • gradle.properties : To configure all project level gradle properties.
  • library.gradle : This file is used to list all library dependency configurations which can be used in modules like app for dependency declarations.

Let’s see how these library configurations are used to declare dependencies in module level build.gradle file. See below image of app level build.gradle file to view how variables of library.gradle file is utilized.

  • config.gradle : This file is used to list all configurations which can be used in modules like app for configuration declarations. It has two methods to generate version name and version code automatically based on variables like versionMajor, versionMinor and versionPatch.

Now let’s see how these configurations can be used in module level build.gradle file. See below image of app level build.gradle file.

Module level build.gradle file : This file contains all the gradle tasks , product flavors and dependency configurations of a module. Check below file

apply plugin: 'com.android.application'
def keystorePropertiesFile = rootProject.file("../../src/NurseCaseManager/keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
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()
vectorDrawables.useSupportLibrary true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
minifyEnabled true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

apply from: "$rootProject.projectDir/buildsystem/library.gradle"

def
library = ext.library;
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])

// android support libraries
compile library.support_compat
compile library.support_recyclerview
compile library.support_cardview
compile library.support_design
compile library.support_vector_drawable
compile library.support_animated_vector_drawable
compile library.support_constraint


// font
compile library.chrisjenx_calligraphy

// image
compile library.glide
annotationProcessor library.glide_compiler

// parser
compile library.gson
//annotationProcessor "com.google.dagger:dagger-compiler:$rootProject.dagger2Version"

compile library.dagger
annotationProcessor "${library.dagger_compiler}"

// logger
compile library.timbler

androidTestCompile library.expresso_core
androidTestCompile library.expresso_intents
androidTestCompile library.mockito_core

compile library.javax_inject
compile library.support_compatv4
provided library.annotation
}

configurations.all {
resolutionStrategy.force library.support_annotationversion
}

Organizing Package Structure

Create packages by features not by Android components. It will make your code more modular and manageable.

In next article we will explore this package structure. For more tips on gradle structure follow references.

I encourage you to follow this series . Be sure to 👏 below to recommend this article. It means a lot to me. Your Comments and suggestions are welcome.

Also, Let’s become friends on Linkedin , Facebook and Twitter

References :