Skip to content

Instantly share code, notes, and snippets.

@wheresjames
Last active April 14, 2020 08:15
Show Gist options
  • Save wheresjames/eb938319a3358fcb529537dc28aabd37 to your computer and use it in GitHub Desktop.
Save wheresjames/eb938319a3358fcb529537dc28aabd37 to your computer and use it in GitHub Desktop.

Gradle Build Script

#!/bin/bash
#--------------------------------------------------------------------
# Created by Robert Umbehant
#--------------------------------------------------------------------
# Install sdkman
#--------------------------------------------------------------------
#
# $ curl -s "https://get.sdkman.io" | bash
#
# Add to .bashrc or run in each terminal
# $ source ~/.sdkman/bin/sdkman-init.sh
#
# Upgrade sdkman
# $ sdk selfupdate force
#
#--------------------------------------------------------------------
# Install gradle
#--------------------------------------------------------------------
#
# $ sdk install gradle
#
#--------------------------------------------------------------------
# Run gradle
#--------------------------------------------------------------------
#
# Get a list of tasks
# $ gradle tasks
#
# Build
# $ gradle :project:build
#
# Run
# $ gradle :project:run
#
# Install debug android apk on first emulator
# $ gradle installDebug
#
# For global build, add following to ~/.gradle/init.gradle
# + gradle.projectsLoaded {
# + rootProject.allprojects {
# + buildDir = "/path/to/build/${rootProject.name}/${project.name}"
# + }
# + }
#
#--------------------------------------------------------------------
# Install JDK
#--------------------------------------------------------------------
#
# https://openjdk.java.net/install/
#
# $ export JDK_HOME=~/Java/jdk-11.0.6+10
# $ export JAVA_HOME=~/Java/jdk-11.0.6+10
#
#--------------------------------------------------------------------
# Install libgdx project tool
#--------------------------------------------------------------------
#
# libgdx project creation tool
# https://libgdx.badlogicgames.com/nightlies/dist/gdx-setup.jar
# https://github.com/libgdx/libgdx/wiki/Project-Setup-Gradle
#
# Convert project to kotlin
# https://stackoverflow.com/questions/51277708/how-to-setup-build-libgdx-kotlin-project-correctly
#
#--------------------------------------------------------------------
# Android
#--------------------------------------------------------------------
#
# Minimal Android project
# https://stackoverflow.com/questions/47167769/hello-world-android-app-with-as-few-files-as-possible-no-ide-and-text-editor/47251607#47251607
#
#--------------------------------------------------------------------
# Example script use
#--------------------------------------------------------------------
#
# Create project
# $ gb.sh create test-project cpp-application
#
# Create GDX Project
# $ gb.sh libgdx-create
#
# Build and Run Project
# $ cd ./test-project
# $ gb.sh desktop-build-run
#
# Sign apk
# $ gb.sh sign-signapk key-name key-password
#
#--------------------------------------------------------------------
#
# Generate privacy policy and TOS
#
# https://app-privacy-policy-generator.firebaseapp.com/
#
#--------------------------------------------------------------------
# Usage
USAGE="USAGE: gb.sh <cmd>"
#--------------------------------------------------------------------
# Functions
#--------------------------------------------------------------------
isCmd()
{
# - separator
FOUND=$(echo "\-$COMMANDLIST-" | grep -o "\-${1}-")
if [[ ! -z $FOUND ]]; then return 0; fi
# , separator
FOUND=$(echo ",$COMMANDLIST," | grep -o ",${1},")
if [[ ! -z $FOUND ]]; then return 0; fi
return -1
}
findInStr()
{
FIND_LIST=$1
FIND_EXISTS=$(echo $FIND_LIST | grep -o $2)
if [[ ! -z $FIND_EXISTS ]]; then return 0; fi
return -1
}
findIn()
{
findInStr "$($1)" $2
return $?
}
showWarning()
{
if [[ 0 -lt ${#@} ]]; then
echo -e "[\e[1;33mWARNING\e[1;0m] \e[1;33m${@}\e[1;0m"
fi
}
exitWithError()
{
if [[ 0 -lt ${#@} ]]; then
echo
echo "--------------------------------------------------------------------"
echo -e "[\e[1;31mERROR\e[1;0m] \e[1;31m${@}\e[1;0m"
echo "--------------------------------------------------------------------"
echo
fi
exit -1
}
exitOnError()
{
if [[ 0 -eq $? ]]; then return 0; fi
exitWithError $@
}
warnOnError()
{
if [[ 0 -eq $? ]]; then return 0; fi
showWarning $@
}
findFile()
{
# Try to find the apk file or root
if [ -z $1 ]; then
FINDFILE="$GRADLE_OUTPUT"
else
if [ -d $1 ]; then
FINDFILE="${1}"
else
FINDFILE="${1}"
fi
fi
FINDTMPL=$2
if [ -z $FINDTMPL ]; then
exitWithError "Find template not specified"
fi
# Do we need to search for an apk file?
if [ -d $FINDFILE ]; then
FINDFILE=$(find $FINDFILE | grep "$FINDTMPL" | head -1)
fi
# Make sure apk file exists
if [ ! -f "$FINDFILE" ]; then
FINDFILE=
fi
}
#--------------------------------------------------------------------
# Command line
#--------------------------------------------------------------------
COMMANDLIST=$1
if [ -z $COMMANDLIST ]; then
echo $USAGE
exit 0
fi
#--------------------------------------------------------------------
# Config
#--------------------------------------------------------------------
SCRIPT_NAME=$(basename $0)
SCRIPT_PATH=$(dirname "$(readlink -f "$0")")
WORKING_PATH=$(pwd)
CURRENT_DATE=$(date '+%Y-%m-%d')
CURRENT_TIME=$(date '+%Y-%m-%d-%H-%M-%S')
# Company info
COMPANYID=$ANDROID_COMPANYID
if [ -z $COMPANYID ]; then
exitWithError "ANDROID_COMPANYID environment variable not defined"
fi
# Gradle
GRADLE="gradle"
GRADLE_PROJECT=
if [ $SCRIPT_PATH != $WORKING_PATH ]; then
GRADLE_PROJECT=$(basename $WORKING_PATH)
fi
if [ -z $GRADLE_BUILD ]; then
GRADLE_BUILD='.'
fi
if [ -z $GRADLE_PROJECT ]; then
GRADLE_OUTPUT="$GRADLE_BUILD"
else
GRADLE_OUTPUT="$GRADLE_BUILD/$GRADLE_PROJECT"
fi
# Android SDK
if [ -z $ANDROID_SDK_ROOT ]; then
ADBEXEC="adb"
EMUEXEC="emulator"
ZIPALIGN="emulator"
showWarning "ANDROID_SDK_ROOT is not set"
else
ADBEXEC="${ANDROID_SDK_ROOT}/platform-tools/adb"
EMUEXEC="${ANDROID_SDK_ROOT}/emulator/emulator"
ZIPALIGN=$(find $ANDROID_SDK_ROOT | grep "zipalign" | head -1)
fi
APKDBG="\-debug\.apk"
APKREL="\-release-unsigned\.apk"
ABBDBG="debug/android.aab"
ABBREL="release/android.aab"
EMULATORVER="Nexus_5X_API_28_x86"
# Java SDK
if [ -z $JDK_HOME ]; then
export JDK_HOME=$JAVA_HOME
fi
# Find Java exe
if [ ! -z $JDK_HOME ]; then
JAVA="${JDK_HOME}/bin/java"
KEYTOOL="${JDK_HOME}/bin/keytool"
JARSIGNER="${JDK_HOME}/bin/jarsigner"
fi
if [ ! -f $JAVA ]; then
JAVA="java"
KEYTOOL="keytool"
JARSIGNER="jarsigner"
fi
# Where does release ouptput go
RELEASE_PATH="$WORKING_PATH/release"
echo "------------------------- Configuration ----------------------------"
echo "- COMPANY ID : $COMPANYID"
echo "- COMMAND LINE : $SCRIPT_NAME $@"
echo "- COMMANDS : $COMMANDLIST"
echo "- SCRIPT : $SCRIPT_NAME"
echo "- SCRIPT PATH : $SCRIPT_PATH"
echo "- WORKING PATH : $WORKING_PATH"
echo "- RELEASE PATH : $RELEASE_PATH"
echo "- GRADLE : $GRADLE"
echo "- GRADLE PROJECT : $GRADLE_PROJECT"
echo "- GRADLE HOME : $GRADLE_HOME"
echo "- GRADLE BUILD : $GRADLE_BUILD"
echo "- GRADLE OUTPUT : $GRADLE_OUTPUT"
echo "- ANDROID SDK : $ANDROID_SDK_ROOT"
echo "- ADB : $ADBEXEC"
echo "- EMULATOR : $EMUEXEC"
echo "- EMULATOR VER : $EMULATORVER"
echo "- ZIPALIGN : $ZIPALIGN"
echo "- JAVA SDK : $JDK_HOME"
echo "- JAVA HOME : $JAVA_HOME"
echo "- JAVA EXEC : $JAVA"
echo "- KEY TOOL : $KEYTOOL"
echo "- JAR SIGNER : $JARSIGNER"
echo "--------------------------------------------------------------------"
echo
#--------------------------------------------------------------------
# Defines
#--------------------------------------------------------------------
#--------------------------------------------------------------------
# Install tools
if isCmd "installtools"; then
# Install sdkman
curl -s "https://get.sdkman.io" | bash
exitOnError "SDKMAN install failed"
# Setup SDKMAN environment variables
source ~/.sdkman/bin/sdkman-init.sh
exitOnError "SDKMAN initialization failed"
# Upgrade sdkman if needed
sdk selfupdate
# Install gradle
sdk install gradle
exit 0
fi
#--------------------------------------------------------------------
# libgdx
if isCmd "libgdx"; then
if isCmd "create"; then
# Setup tool file name
GDXSETUP="$SCRIPT_PATH/gdx-setup.jar"
GDXLINK="https://libgdx.badlogicgames.com/nightlies/dist/gdx-setup.jar"
# Download the tool if we don't have it
if [ ! -f $GDXSETUP ]; then
echo "Downloading GDX project setup tool..."
echo
curl -L $GDXLINK -o $GDXSETUP
exitOnError "Failed to download GDX Setup tool"
fi
if [ -z $2 ]; then
# Run the tool
nohup $JAVA -jar $GDXSETUP &
else
# https://github.com/libgdx/libgdx/wiki/Project-Setup-Gradle
DIR=$2
NAME=$2
$JAVA -jar $GDXSETUP --dir "$DIR" --name "$NAME" \
--package "com.mycompany.$NAME" --mainClass "App$NAME" \
--sdkLocation "$ANDROID_SDK_ROOT" --excludeModules HTML
# --excludeModules Desktop; Android; iOS; HTML
# --extensions Bullet; Freetype; Tools; Controllers; Box2d; Box2dlights; Ashley; Ai
fi
echo
echo "--------------------------------------------------------------------"
exit 0
fi
fi
#--------------------------------------------------------------------
# Create new project
if isCmd "create"; then
echo "--------------------------------------------------------------------"
echo "- Creating project"
echo "--------------------------------------------------------------------"
echo "- https://docs.gradle.org/current/userguide/build_init_plugin.html"
echo "--------------------------------------------------------------------"
if [ -z $2 ]; then
echo "${USAGE} <directory> <project-type>"
exitWithError "Project directory not specified"
fi
if [ -z $3 ]; then
echo "${USAGE} <directory> <project-type>"
echo
echo "Examples project types"
echo " basic, kotlin-application, cpp-application, cpp-library, ..."
exitWithError "Project type not specified"
fi
DIR="${2}"
if [ -d $DIR ]; then
exitWithError "Directory already exists : $DIR"
fi
PROJECTTYPE=$3
mkdir -p $DIR
cd $DIR
gradle init --type=${PROJECTTYPE}
exitOnError "gradle init failed"
cd $WORKING_PATH
exit 0
fi
#--------------------------------------------------------------------
# Android app
if isCmd "android"; then
USAGE="$USAGE <project>"
PROJECT=$2
if [ "." = "$PROJECT" ]; then
PROJECT=
elif [ ! -z $PROJECT ]; then
PROJECT="$PROJECT"
echo "PROJECT : $PROJECT"
fi
# Build
if isCmd "build"; then
echo "Building..."
$GRADLE "${PROJECT}:build"
echo "Creating bundle..."
$GRADLE "${PROJECT}:bundle"
exitOnError "gradle build failed"
fi
# List devices
if isCmd "restart"; then
$ADBEXEC kill-server
$ADBEXEC start-server
$ADBEXEC devices
fi
# List devices
if isCmd "devices"; then
echo "List adb devices..."
$ADBEXEC devices
fi
# Install apk file into emulator
if isCmd "install"; then
DEVICE="$2"
APPNAME="$3"
findFile "$4" "$APKDBG"
APKFILE=$FINDFILE
# Make sure apk file exists
if [ ! -f "$APKFILE" ]; then
echo "${USAGE} <deviceid> <apk-file | project-root-dir>"
echo
exitWithError "APK file not found : $APKFILE"
fi
if [ "." = "$APPNAME" ]; then
APPNAME=
fi
if [ -z $APPNAME ]; then
if [ ! -z $GRADLE_PROJECT ]; then
APPNAME="com.${COMPANYID}.${GRADLE_PROJECT}"
fi
fi
if [ ! -z $APPNAME ]; then
echo "Uninstalling : $APPNAME"
$ADBEXEC -s $DEVICE uninstall "$APPNAME"
fi
echo "Installing : $DEV <- $APKFILE"
$ADBEXEC -s $DEVICE install "$APKFILE"
exitOnError "Install failed"
fi
# Run in the emulator
if isCmd "run"; then
echo "Running..."
# Find the apk file
findFile "$3" "$APKDBG"
APKFILE=$FINDFILE
# Make sure apk file exists
if [ ! -f "$APKFILE" ]; then
echo "${USAGE} <apk-file | project-root-dir>"
echo
exitWithError "APK file not found : $APKFILE"
fi
echo "APK FILE : $APKFILE"
# Attempt to grab a device
DEVICE=$($ADBEXEC devices | grep -Eo emulator\-.*$ | grep -Eo [a-z]+\-[0-9]+)
# Start the emulator if we didn't get a device
if [ -z $DEVICE ]; then
showWarning "No running emulators found, starting a new emulator..."
nohup $EMUEXEC -avd $EMULATORVER -netdelay none -netspeed full &
echo "Waiting for emulator to start..."
while ! findIn "$ADBEXEC devices" "emulator-"; do
printf .
sleep 1
done
echo
# Try again for device name
DEVICE=$($ADBEXEC devices | grep -Eo emulator\-.*$ | grep -Eo [a-z]+\-[0-9]+)
if [ -z $DEVICE ]; then
exitWithError "Failed to get device name"
fi
# Uninstall the old app
if [ ! -z $GRADLE_PROJECT ]; then
APPNAME="com.${COMPANYID}.${GRADLE_PROJECT}"
echo "Uninstalling : $APPNAME"
$ADBEXEC -s $DEVICE uninstall "$APPNAME"
fi
echo "Installing : $DEVICE <- $APKFILE"
retry=0
until [ $retry -gt 10 ]; do
if [ $retry -gt 0 ]; then
echo "Attempt $retry failed : Retrying in 10 seconds..."
sleep 10
fi
((retry++))
$ADBEXEC -s $DEVICE install $APKFILE
if [[ 0 -eq $? ]]; then
retry=999
fi
done
else
echo "Installing : $DEVICE <- $APKFILE"
$ADBEXEC -s $DEVICE install $APKFILE
exitOnError "adb install failed"
fi
fi
# Start emulator
if isCmd "emulator"; then
echo "Starting emulator..."
# Start emulator
$EMUEXEC -avd $EMULATORVER -netdelay none -netspeed full &
exitOnError "launch emulator failed"
fi
if isCmd "release"; then
# Find the apk file
findFile "$3" "$APKREL"
APKFILE=$FINDFILE
if [ ! -f "$APKFILE" ]; then
echo "${USAGE} [apk-file | project-root-dir]"
echo
exitWithError "APK file not found : $APKFILE"
fi
echo "APKFILE = $APKFILE"
APKRELEASE="$RELEASE_PATH/$COMPANYID-$GRADLE_PROJECT-$CURRENT_TIME.apk"
# Ensure release directory
mkdir -p "$RELEASE_PATH"
cp $APKFILE $APKRELEASE
echo "APK Release : $APKRELEASE"
fi
fi
#--------------------------------------------------------------------
# Local app
if isCmd "local"; then
# Build
if isCmd "build"; then
echo "Building..."
GRADLECMD="build"
if [ ! -z $2 ]; then
GRADLECMD=":$2:${GRADLECMD}"
fi
echo "--------------------------------------------------------------------"
echo "- $GRADLE $GRADLECMD"
echo "--------------------------------------------------------------------"
$GRADLE $GRADLECMD
exitOnError "$GRADLE $GRADLECMD failed"
fi
if isCmd "run"; then
echo "Running..."
GRADLECMD="run"
if [ ! -z $2 ]; then
GRADLECMD=":$2:${GRADLECMD}"
fi
echo "--------------------------------------------------------------------"
echo "- $GRADLE $GRADLECMD"
echo "--------------------------------------------------------------------"
$GRADLE $GRADLECMD
exitOnError "$GRADLE $GRADLECMD failed"
fi
fi
if isCmd "sign"; then
if isCmd "genkey"; then
KEYNAME=$2
if [ -z "$KEYNAME" ]; then
echo "${USAGE} <key-name>"
echo
exitWithError "Key name not specified"
fi
KEYSTORE="$WORKING_PATH/keys/$KEYNAME.keystore"
mkdir -p "$WORKING_PATH/keys"
# Generate key
$KEYTOOL -genkey -v -keystore $KEYSTORE -alias $KEYNAME -keyalg RSA -keysize 2048 -validity 10000
fi
if isCmd "export"; then
KEYNAME=$2
if [ -z "$KEYNAME" ]; then
echo "${USAGE} <key-name>"
echo
exitWithError "Key name not specified"
fi
# Setup tool file name
PEPEXEC="$SCRIPT_PATH/pepk.jar"
PEPLINK="https://www.gstatic.com/play-apps-publisher-rapid/signing-tool/prod/pepk.jar"
# Download the tool if we don't have it
if [ ! -f $PEPEXEC ]; then
echo "Downloading GDX project setup tool..."
echo
curl -L $PEPLINK -o $PEPEXEC
exitOnError "Failed to download GDX Setup tool"
fi
KEYSTORE="$WORKING_PATH/keys/$KEYNAME.keystore"
if [ ! -f $KEYSTORE ]; then
exitWithError "Invalid keystore : $KEYSTORE"
fi
PLAYKEYFILE="$WORKING_PATH/keys/playstore.key"
if [ ! -f $PLAYKEYFILE ]; then
exitWithError "Invalid playstore keystore : $PLAYKEYFILE"
fi
PLAYKEY=`cat $PLAYKEYFILE`
if [ -z $PLAYKEY ]; then
exitWithError "Empty playstore keystore : $PLAYKEYFILE"
fi
$JAVA -jar $PEPEXEC --keystore=$KEYSTORE \
--alias=$KEYNAME \
--output=$KEYNAME-playstorekey.zip \
--encryptionkey=$PLAYKEY \
--include-cert
fi
if isCmd "signapk"; then
KEYNAME=$2
if [ -z "$KEYNAME" ]; then
echo "${USAGE} <key-name> <key-password> [apk-file | project-root-dir]"
echo
exitWithError "Key name not specified"
fi
KEYPASSWORD=$3
if [ -z "$KEYPASSWORD" ]; then
echo "${USAGE} <key-name> <key-password> [apk-file | project-root-dir]"
echo
exitWithError "Key password not specified"
fi
# Find the apk file
findFile "$4" "$APKREL"
APKFILE=$FINDFILE
if [ ! -f "$APKFILE" ]; then
echo "${USAGE} <key-name> <key-password> [apk-file | project-root-dir]"
echo
exitWithError "APK file not found : $APKFILE"
fi
echo "APKFILE = $APKFILE"
KEYSTORE="$WORKING_PATH/keys/$KEYNAME.keystore"
APK_UNALIGNED="$RELEASE_PATH/$COMPANYID-$GRADLE_PROJECT-$CURRENT_TIME-unaligned.apk"
APK_ALIGNED="$RELEASE_PATH/$COMPANYID-$GRADLE_PROJECT-$CURRENT_TIME.apk"
# Ensure release directory
mkdir -p "$RELEASE_PATH"
cp $APKFILE $APK_UNALIGNED
echo "Signing apk : $APK_UNALIGNED"
$JARSIGNER -sigalg SHA1withRSA -digestalg SHA1 -keystore $KEYSTORE -storepass $KEYPASSWORD $APK_UNALIGNED $KEYNAME
exitOnError "APK Signing failed"
echo "Aligning apk : $APK_ALIGNED"
$ZIPALIGN -v 4 $APK_UNALIGNED $APK_ALIGNED
exitOnError "APK Alignment failed"
rm $APK_UNALIGNED
fi
if isCmd "signaab"; then
KEYNAME=$2
if [ -z "$KEYNAME" ]; then
echo "${USAGE} <key-name> <key-password> [aab-file | project-root-dir]"
echo
exitWithError "Key name not specified"
fi
KEYPASSWORD=$3
if [ -z "$KEYPASSWORD" ]; then
echo "${USAGE} <key-name> <key-password> [aab-file | project-root-dir]"
echo
exitWithError "Key password not specified"
fi
# Find the aab file
findFile "$4" "$ABBREL"
AABFILE=$FINDFILE
if [ ! -f "$AABFILE" ]; then
echo "${USAGE} <key-name> <key-password> [aab-file | project-root-dir]"
echo
exitWithError "AAB file not found : $AABFILE"
fi
echo "AABFILE = $AABFILE"
KEYSTORE="$WORKING_PATH/keys/$KEYNAME.keystore"
AABOUT="$RELEASE_PATH/$COMPANYID-$GRADLE_PROJECT-$CURRENT_TIME.aab"
# Ensure release directory
mkdir -p "$RELEASE_PATH"
cp $AABFILE $AABOUT
echo "Signing aab : $AABOUT"
$JARSIGNER -sigalg SHA1withRSA -digestalg SHA1 -keystore $KEYSTORE -storepass $KEYPASSWORD $AABOUT $KEYNAME
exitOnError "AAB Signing failed"
fi
fi
echo "--------------------------------------------------------------------"
echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment