Create a minimal Android boilerplate from scratch

Create a minimal Android boilerplate from scratch

In this post, I will introduce how to create an Android application from the command line, without the help of any IDE such as Android Studio.

If you are new to Android development, by following this post, I believe you will have a better understanding of how an Android application is constructed and how it works.

If you are already familiar with Android development, you might feel this post useless. And I also recommend using IDE for a production app.

The final source code is published here.


Step 1: Download gradle from https://gradle.org/releases/.

Step 2: Create settings.gradle with:

rootProject.name = 'reactNativeBoilerplate'

Step 3: Run gradle wrapper. This script will generate the following file and directories:

  • gradle/
  • gralew
  • gradlew.bat

Step 4: Modify settings.gradle:

rootProject.name = 'reactNativeBoilerplate'
include ':app'

Step 5: Create the following files:

  • .gitignore:
.gradle/
.DS_Store
build/
local.properties
  • build.gradle:
buildscript {
    ext {
        buildToolsVersion = "29.0.3"
        minSdkVersion = 21
        compileSdkVersion = 29
        targetSdkVersion = 29
        ndkVersion = "20.1.5948944"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:4.1.0")
    }
}

allprojects {
    repositories {
        mavenLocal()
        google()
        mavenCentral()
        maven { url 'https://www.jitpack.io' }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
  • app/build.gralde:
apply plugin: 'com.android.application'

import com.android.build.OutputFile

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

android {
    compileSdkVersion 25
    defaultConfig {
        applicationId "com.transang.reactNativeBoilerplate"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    implementation 'com.android.support:appcompat-v7:25.3.1'
}
  • app/proguard-rules.pro:
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:
  • app/src/main/res/values/styles.xml:
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="android:textColor">#000000</item>
    </style>

</resources>
  • app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.transang.reactNativeBoilerplate">

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

    <application
      android:label="@string/app_name"
      android:allowBackup="false"
      android:theme="@style/AppTheme"
        >
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
        android:launchMode="singleTask"
        android:windowSoftInputMode="adjustResize"
          >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
    </application>
</manifest>
  • app/src/main/res/values/strings.xml:
<resources>
    <string name="app_name">React Native Boilerplate</string>
</resources>
  • app/src/main/java/com/transang/reactNativeBoilerplate/MainActivity.java:
package com.transang.reactNativeBoilerplate;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
  • app/src/main/res/layout/activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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" />

</android.support.constraint.ConstraintLayout>

Step 6: Build the application with ./gradlew build.

> Task :app:lint
Execution optimizations have been disabled for task ':app:lint' to ensure correctness due to the following reasons:
  - Type 'com.android.build.gradle.tasks.LintGlobalTask' property 'allInputs' cannot be resolved:  Cannot convert the provided notation to a File or URI: constraint-layout-1.1.2.aar (com.android.support.constraint:constraint-layout:1.1.2). The following types/formats are supported:  - A String or CharSequence path, for example 'src/main/java' or '/usr/include'. - A String or CharSequence URI, for example 'file:/usr/include'. - A File instance. - A Path instance. - A Directory instance. - A RegularFile instance. - A URI or URL instance. - A TextResource instance. Reason: An input file collection couldn't be resolved, making it impossible to determine task inputs. Please refer to https://docs.gradle.org/7.0.1/userguide/validation_problems.html#unresolvable_input for more details about this problem.
Ran lint on variant debug: 3 issues found
Ran lint on variant release: 3 issues found
Wrote HTML report to file:///home/transang/react-native-boilderplate/android/app/build/reports/lint-results.html
Wrote XML report to file:///home/transang/react-native-boilderplate/android/app/build/reports/lint-results.xml

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/7.0.1/userguide/command_line_interface.html#sec:command_line_warnings

Execution optimizations have been disabled for 1 invalid unit(s) of work during this build to ensure correctness.
Please consult deprecation warnings for more details.

BUILD SUCCESSFUL in 1s
55 actionable tasks: 13 executed, 42 up-to-date

This command will generate a directory app/build with the apk files at app/build/outputs/apk/{debug,release}.

Step 7: Install the app with ./gradlew installDebug.

Step 8: Now, you can open the app from the device or emulator.