Refactor android-builder into command scripts
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
# Bugs / TODO
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
|
||||||
|
- `install.sh` defaults `ANDROID_BUILDER_REPO` to `http://192.168.1.46:8085/Dark98/Termux-Android-Builder.git`, which only works on the local LAN setup. If this repo is meant to be portable, the default should point to a stable remote or be documented as LAN-only.
|
||||||
|
- The generated `gradlew` wrapper just forwards to the system `gradle` package. That is convenient in Termux, but it means builds are not pinned to a project-specific Gradle wrapper version.
|
||||||
|
- The generated app pins Android Gradle Plugin `8.5.2` without pinning a compatible Gradle wrapper version. That can break when the installed Gradle package changes or is incompatible with that plugin version.
|
||||||
|
- The CLI is now split into a dispatcher plus per-command scripts under `lib/commands/`, which improves readability but adds more files to maintain.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- Decide whether the default repo URL in `install.sh` should stay LAN-specific or be replaced with a public canonical URL.
|
||||||
|
- Consider generating a real Gradle wrapper for new projects instead of relying on `gradle` from Termux.
|
||||||
+10
-370
@@ -1,378 +1,18 @@
|
|||||||
#!/data/data/com.termux/files/usr/bin/bash
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
AB_HOME="${ANDROID_BUILDER_HOME:-$HOME/android-builder}"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
SDK="$HOME/android-sdk"
|
COMMAND="${1:-help}"
|
||||||
PLATFORM="${ANDROID_BUILDER_PLATFORM:-android-33}"
|
TARGET="$COMMAND"
|
||||||
|
|
||||||
get_project_name() {
|
|
||||||
if [ -f settings.gradle ]; then
|
|
||||||
DETECTED_NAME="$(grep -E '^rootProject.name[[:space:]]*=' settings.gradle \
|
|
||||||
| sed -E 's/.*=[[:space:]]*["'\'']?([^"'\'' ]+)["'\'']?.*/\1/' \
|
|
||||||
| head -n 1)"
|
|
||||||
|
|
||||||
[ -n "$DETECTED_NAME" ] && echo "$DETECTED_NAME" && return
|
|
||||||
fi
|
|
||||||
|
|
||||||
basename "$PWD"
|
|
||||||
}
|
|
||||||
|
|
||||||
get_build_type() {
|
|
||||||
echo "${ANDROID_BUILDER_BUILD_TYPE:-debug}"
|
|
||||||
}
|
|
||||||
|
|
||||||
get_apk_path() {
|
|
||||||
case "$(get_build_type)" in
|
|
||||||
debug) echo "app/build/outputs/apk/debug/app-debug.apk" ;;
|
|
||||||
release) echo "app/build/outputs/apk/release/app-release.apk" ;;
|
|
||||||
*) return 1 ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
echo "==> Installing packages"
|
|
||||||
pkg update -y
|
|
||||||
pkg install -y git curl wget unzip zip nano \
|
|
||||||
openjdk-21 gradle aapt2 apksigner d8 dx android-tools
|
|
||||||
|
|
||||||
echo "==> Configuring Java"
|
|
||||||
JAVA_BIN="$(command -v java)"
|
|
||||||
JAVA_HOME_DETECTED="$(dirname "$(dirname "$(readlink -f "$JAVA_BIN")")")"
|
|
||||||
export JAVA_HOME="$JAVA_HOME_DETECTED"
|
|
||||||
export PATH="$JAVA_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
touch "$HOME/.bashrc"
|
|
||||||
grep -q 'ANDROID_BUILDER_JAVA_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" <<EOF2
|
|
||||||
|
|
||||||
# Java for AndroidBuilder
|
|
||||||
export JAVA_HOME=$JAVA_HOME_DETECTED
|
|
||||||
export PATH=\$JAVA_HOME/bin:\$PATH
|
|
||||||
export ANDROID_BUILDER_JAVA_HOME=\$JAVA_HOME
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
echo "==> Installing Android SDK cmdline-tools"
|
|
||||||
mkdir -p "$SDK/cmdline-tools"
|
|
||||||
cd "$SDK/cmdline-tools"
|
|
||||||
|
|
||||||
if [ ! -d latest ]; then
|
|
||||||
wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdline-tools.zip
|
|
||||||
unzip -q cmdline-tools.zip
|
|
||||||
mv cmdline-tools latest
|
|
||||||
rm cmdline-tools.zip
|
|
||||||
fi
|
|
||||||
|
|
||||||
export ANDROID_HOME="$SDK"
|
|
||||||
export ANDROID_SDK_ROOT="$SDK"
|
|
||||||
export PATH="$SDK/cmdline-tools/latest/bin:$PATH"
|
|
||||||
|
|
||||||
grep -q 'ANDROID_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" <<'EOF2'
|
|
||||||
|
|
||||||
# AndroidBuilder SDK environment
|
|
||||||
export ANDROID_HOME=$HOME/android-sdk
|
|
||||||
export ANDROID_SDK_ROOT=$ANDROID_HOME
|
|
||||||
export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$PATH
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
echo "==> Accepting Android SDK licenses"
|
|
||||||
mkdir -p "$SDK/licenses"
|
|
||||||
cat > "$SDK/licenses/android-sdk-license" <<'EOF2'
|
|
||||||
24333f8a63b6825ea9c5514f83c2829b004d1fee
|
|
||||||
d56f5187479451eabf01fb78af6dfcb131a6481e
|
|
||||||
8933bad161af4178b1185d1a37fbf41ea5269c55
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
echo "==> Installing SDK platform: $PLATFORM"
|
|
||||||
sdkmanager "platforms;$PLATFORM"
|
|
||||||
|
|
||||||
echo "==> Writing Gradle config"
|
|
||||||
mkdir -p "$HOME/.gradle"
|
|
||||||
cat > "$HOME/.gradle/gradle.properties" <<EOF2
|
|
||||||
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
|
|
||||||
org.gradle.daemon=true
|
|
||||||
org.gradle.parallel=true
|
|
||||||
org.gradle.caching=true
|
|
||||||
android.aapt2FromMavenOverride=$PREFIX/bin/aapt2
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "Setup complete."
|
|
||||||
}
|
|
||||||
|
|
||||||
doctor() {
|
|
||||||
echo "AndroidBuilder Doctor"
|
|
||||||
echo
|
|
||||||
|
|
||||||
java -version
|
|
||||||
echo
|
|
||||||
gradle -v | grep Gradle
|
|
||||||
echo
|
|
||||||
aapt2 version
|
|
||||||
echo
|
|
||||||
|
|
||||||
test -f "$SDK/platforms/$PLATFORM/android.jar" \
|
|
||||||
&& echo "android.jar: found" \
|
|
||||||
|| echo "android.jar: missing"
|
|
||||||
}
|
|
||||||
|
|
||||||
new_project() {
|
|
||||||
NAME="$1"
|
|
||||||
TEMPLATE="hello"
|
|
||||||
shift || true
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
--template|-t)
|
|
||||||
TEMPLATE="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown option: $1"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$NAME" ]; then
|
|
||||||
echo "Usage: android-builder new MyApp [--template hello|empty]"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$TEMPLATE" in
|
|
||||||
hello) create_base_project "$NAME" "Hello, World!" ;;
|
|
||||||
empty) create_base_project "$NAME" "" ;;
|
|
||||||
*)
|
|
||||||
echo "Unknown template: $TEMPLATE"
|
|
||||||
echo "Available templates: hello, empty"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
create_base_project() {
|
|
||||||
NAME="$1"
|
|
||||||
MESSAGE="$2"
|
|
||||||
PACKAGE="com.example.$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9')"
|
|
||||||
PACKAGE_PATH="$(echo "$PACKAGE" | tr '.' '/')"
|
|
||||||
|
|
||||||
mkdir -p "$NAME/app/src/main/java/$PACKAGE_PATH"
|
|
||||||
mkdir -p "$NAME/app/src/main/res/values"
|
|
||||||
|
|
||||||
cat > "$NAME/settings.gradle" <<EOF2
|
|
||||||
pluginManagement { repositories { google(); mavenCentral(); gradlePluginPortal() } }
|
|
||||||
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS); repositories { google(); mavenCentral() } }
|
|
||||||
rootProject.name="$NAME"
|
|
||||||
include(":app")
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/build.gradle" <<'EOF2'
|
|
||||||
// Root build file intentionally minimal.
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/gradle.properties" <<EOF2
|
|
||||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
|
||||||
org.gradle.daemon=true
|
|
||||||
org.gradle.parallel=true
|
|
||||||
org.gradle.caching=true
|
|
||||||
android.aapt2FromMavenOverride=$PREFIX/bin/aapt2
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/local.properties" <<EOF2
|
|
||||||
sdk.dir=$SDK
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/app/build.gradle" <<EOF2
|
|
||||||
plugins {
|
|
||||||
id 'com.android.application' version '8.5.2'
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace '$PACKAGE'
|
|
||||||
compileSdk 33
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "$PACKAGE"
|
|
||||||
minSdk 24
|
|
||||||
targetSdk 33
|
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/app/src/main/AndroidManifest.xml" <<'EOF2'
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<application
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:theme="@style/AppTheme">
|
|
||||||
<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>
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/app/src/main/res/values/strings.xml" <<EOF2
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">$NAME</string>
|
|
||||||
</resources>
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/app/src/main/res/values/styles.xml" <<'EOF2'
|
|
||||||
<resources>
|
|
||||||
<style name="AppTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
|
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/app/src/main/java/$PACKAGE_PATH/MainActivity.java" <<EOF2
|
|
||||||
package $PACKAGE;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
public class MainActivity extends Activity {
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
LinearLayout layout = new LinearLayout(this);
|
|
||||||
layout.setGravity(Gravity.CENTER);
|
|
||||||
layout.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
layout.setPadding(32, 32, 32, 32);
|
|
||||||
|
|
||||||
TextView title = new TextView(this);
|
|
||||||
title.setText("$NAME");
|
|
||||||
title.setTextSize(30);
|
|
||||||
title.setGravity(Gravity.CENTER);
|
|
||||||
|
|
||||||
TextView message = new TextView(this);
|
|
||||||
message.setText("$MESSAGE");
|
|
||||||
message.setTextSize(18);
|
|
||||||
message.setGravity(Gravity.CENTER);
|
|
||||||
|
|
||||||
layout.addView(title);
|
|
||||||
layout.addView(message);
|
|
||||||
|
|
||||||
setContentView(layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
cat > "$NAME/gradlew" <<'EOF2'
|
|
||||||
#!/data/data/com.termux/files/usr/bin/bash
|
|
||||||
set -e
|
|
||||||
exec gradle "$@"
|
|
||||||
EOF2
|
|
||||||
|
|
||||||
chmod +x "$NAME/gradlew"
|
|
||||||
|
|
||||||
echo "Created project: $NAME"
|
|
||||||
echo
|
|
||||||
echo "Next:"
|
|
||||||
echo " cd $NAME"
|
|
||||||
echo " android-builder build"
|
|
||||||
echo " android-builder export"
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
test -f local.properties || echo "sdk.dir=$SDK" > local.properties
|
|
||||||
|
|
||||||
if [ -f ./gradlew ]; then
|
|
||||||
chmod +x ./gradlew
|
|
||||||
./gradlew assembleDebug
|
|
||||||
else
|
|
||||||
gradle assembleDebug
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
export_apk() {
|
|
||||||
APK="$(get_apk_path)"
|
|
||||||
BUILD_TYPE="$(get_build_type)"
|
|
||||||
|
|
||||||
if [ ! -f "$APK" ]; then
|
|
||||||
echo "No $BUILD_TYPE APK found."
|
|
||||||
echo
|
|
||||||
echo "Run:"
|
|
||||||
echo " android-builder build"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "$HOME/storage" ]; then
|
|
||||||
echo "==> Termux storage has not been configured."
|
|
||||||
echo "==> Requesting storage permission..."
|
|
||||||
echo
|
|
||||||
|
|
||||||
termux-setup-storage
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "Please grant storage permission, then run:"
|
|
||||||
echo " android-builder export"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
EXPORT_DIR="$HOME/storage/documents"
|
|
||||||
mkdir -p "$EXPORT_DIR"
|
|
||||||
|
|
||||||
PROJECT_NAME="$(get_project_name)"
|
|
||||||
DEST="$EXPORT_DIR/${PROJECT_NAME}.apk"
|
|
||||||
|
|
||||||
echo "==> Exporting APK..."
|
|
||||||
|
|
||||||
cp -f "$APK" "$DEST"
|
|
||||||
sync
|
|
||||||
|
|
||||||
SIZE="$(du -h "$DEST" | cut -f1)"
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "✓ Export complete!"
|
|
||||||
echo
|
|
||||||
echo "Project:"
|
|
||||||
echo " $PROJECT_NAME"
|
|
||||||
echo
|
|
||||||
echo "Build:"
|
|
||||||
echo " $BUILD_TYPE"
|
|
||||||
echo
|
|
||||||
echo "Size:"
|
|
||||||
echo " $SIZE"
|
|
||||||
echo
|
|
||||||
echo "Location:"
|
|
||||||
echo " $DEST"
|
|
||||||
echo
|
|
||||||
echo "Open your file manager, browse to Documents,"
|
|
||||||
echo "then tap ${PROJECT_NAME}.apk to install or share it."
|
|
||||||
}
|
|
||||||
|
|
||||||
help() {
|
|
||||||
echo "AndroidBuilder"
|
|
||||||
echo
|
|
||||||
echo "Usage:"
|
|
||||||
echo " android-builder setup"
|
|
||||||
echo " android-builder doctor"
|
|
||||||
echo " android-builder new MyApp"
|
|
||||||
echo " android-builder new MyApp --template empty"
|
|
||||||
echo " android-builder build"
|
|
||||||
echo " android-builder export"
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND="$1"
|
|
||||||
shift || true
|
|
||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
setup) setup "$@" ;;
|
setup|doctor|new|build|export|help|-h|--help)
|
||||||
doctor) doctor "$@" ;;
|
case "$COMMAND" in
|
||||||
new) new_project "$@" ;;
|
-h|--help) TARGET="help" ;;
|
||||||
build) build "$@" ;;
|
esac
|
||||||
export) export_apk "$@" ;;
|
shift || true
|
||||||
help|-h|--help|"") help ;;
|
exec "$ROOT_DIR/lib/commands/$TARGET.sh" "$@"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown command: $COMMAND"
|
echo "Unknown command: $COMMAND"
|
||||||
echo "Run: android-builder help"
|
echo "Run: android-builder help"
|
||||||
|
|||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
source "$ROOT_DIR/lib/common.sh"
|
||||||
|
|
||||||
|
test -f local.properties || echo "sdk.dir=$SDK" > local.properties
|
||||||
|
|
||||||
|
BUILD_TYPE="$(get_build_type)"
|
||||||
|
case "$BUILD_TYPE" in
|
||||||
|
debug) TASK="assembleDebug" ;;
|
||||||
|
release) TASK="assembleRelease" ;;
|
||||||
|
*)
|
||||||
|
echo "Unknown build type: $BUILD_TYPE"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -f ./gradlew ]; then
|
||||||
|
chmod +x ./gradlew
|
||||||
|
./gradlew "$TASK"
|
||||||
|
else
|
||||||
|
gradle "$TASK"
|
||||||
|
fi
|
||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
source "$ROOT_DIR/lib/common.sh"
|
||||||
|
|
||||||
|
echo "AndroidBuilder Doctor"
|
||||||
|
echo
|
||||||
|
|
||||||
|
java -version
|
||||||
|
echo
|
||||||
|
gradle -v | grep Gradle
|
||||||
|
echo
|
||||||
|
aapt2 version
|
||||||
|
echo
|
||||||
|
|
||||||
|
test -f "$SDK/platforms/$PLATFORM/android.jar" \
|
||||||
|
&& echo "android.jar: found" \
|
||||||
|
|| echo "android.jar: missing"
|
||||||
Executable
+60
@@ -0,0 +1,60 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
source "$ROOT_DIR/lib/common.sh"
|
||||||
|
|
||||||
|
APK="$(get_apk_path)"
|
||||||
|
BUILD_TYPE="$(get_build_type)"
|
||||||
|
|
||||||
|
if [ ! -f "$APK" ]; then
|
||||||
|
echo "No $BUILD_TYPE APK found."
|
||||||
|
echo
|
||||||
|
echo "Run:"
|
||||||
|
echo " android-builder build"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$HOME/storage" ]; then
|
||||||
|
echo "==> Termux storage has not been configured."
|
||||||
|
echo "==> Requesting storage permission..."
|
||||||
|
echo
|
||||||
|
|
||||||
|
termux-setup-storage
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Please grant storage permission, then run:"
|
||||||
|
echo " android-builder export"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
EXPORT_DIR="$HOME/storage/documents"
|
||||||
|
mkdir -p "$EXPORT_DIR"
|
||||||
|
|
||||||
|
PROJECT_NAME="$(get_project_name)"
|
||||||
|
DEST="$EXPORT_DIR/${PROJECT_NAME}.apk"
|
||||||
|
|
||||||
|
echo "==> Exporting APK..."
|
||||||
|
|
||||||
|
cp -f "$APK" "$DEST"
|
||||||
|
sync
|
||||||
|
|
||||||
|
SIZE="$(du -h "$DEST" | cut -f1)"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "✓ Export complete!"
|
||||||
|
echo
|
||||||
|
echo "Project:"
|
||||||
|
echo " $PROJECT_NAME"
|
||||||
|
echo
|
||||||
|
echo "Build:"
|
||||||
|
echo " $BUILD_TYPE"
|
||||||
|
echo
|
||||||
|
echo "Size:"
|
||||||
|
echo " $SIZE"
|
||||||
|
echo
|
||||||
|
echo "Location:"
|
||||||
|
echo " $DEST"
|
||||||
|
echo
|
||||||
|
echo "Open your file manager, browse to Documents,"
|
||||||
|
echo "then tap ${PROJECT_NAME}.apk to install or share it."
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "AndroidBuilder"
|
||||||
|
echo
|
||||||
|
echo "Usage:"
|
||||||
|
echo " android-builder setup"
|
||||||
|
echo " android-builder doctor"
|
||||||
|
echo " android-builder new MyApp"
|
||||||
|
echo " android-builder new MyApp --template empty"
|
||||||
|
echo " android-builder build"
|
||||||
|
echo " android-builder export"
|
||||||
Executable
+53
@@ -0,0 +1,53 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
source "$ROOT_DIR/lib/common.sh"
|
||||||
|
|
||||||
|
NAME=""
|
||||||
|
TEMPLATE="hello"
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--template|-t)
|
||||||
|
if [ $# -lt 2 ] || [ -z "${2:-}" ] || [ "${2#-}" != "$2" ]; then
|
||||||
|
echo "Error: --template requires a value"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
TEMPLATE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--template=*)
|
||||||
|
TEMPLATE="${1#*=}"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ -z "$NAME" ]; then
|
||||||
|
NAME="$1"
|
||||||
|
else
|
||||||
|
echo "Unknown argument: $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$NAME" ]; then
|
||||||
|
echo "Usage: android-builder new MyApp [--template hello|empty]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$TEMPLATE" in
|
||||||
|
hello) create_base_project "$NAME" "Hello, World!" ;;
|
||||||
|
empty) create_base_project "$NAME" "" ;;
|
||||||
|
*)
|
||||||
|
echo "Unknown template: $TEMPLATE"
|
||||||
|
echo "Available templates: hello, empty"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
source "$ROOT_DIR/lib/common.sh"
|
||||||
|
|
||||||
|
ensure_termux
|
||||||
|
|
||||||
|
echo "==> Installing packages"
|
||||||
|
pkg update -y
|
||||||
|
pkg install -y git curl wget unzip zip nano \
|
||||||
|
openjdk-21 gradle aapt2 apksigner d8 dx android-tools
|
||||||
|
|
||||||
|
echo "==> Configuring Java"
|
||||||
|
JAVA_BIN="$(command -v java)"
|
||||||
|
JAVA_HOME_DETECTED="$(dirname "$(dirname "$(readlink -f "$JAVA_BIN")")")"
|
||||||
|
export JAVA_HOME="$JAVA_HOME_DETECTED"
|
||||||
|
export PATH="$JAVA_HOME/bin:$PATH"
|
||||||
|
|
||||||
|
touch "$HOME/.bashrc"
|
||||||
|
grep -q 'ANDROID_BUILDER_JAVA_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" <<EOF2
|
||||||
|
|
||||||
|
# Java for AndroidBuilder
|
||||||
|
export JAVA_HOME=$JAVA_HOME_DETECTED
|
||||||
|
export PATH=\$JAVA_HOME/bin:\$PATH
|
||||||
|
export ANDROID_BUILDER_JAVA_HOME=\$JAVA_HOME
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
echo "==> Installing Android SDK cmdline-tools"
|
||||||
|
mkdir -p "$SDK/cmdline-tools"
|
||||||
|
cd "$SDK/cmdline-tools"
|
||||||
|
|
||||||
|
if [ ! -d latest ]; then
|
||||||
|
wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdline-tools.zip
|
||||||
|
unzip -q cmdline-tools.zip
|
||||||
|
mv cmdline-tools latest
|
||||||
|
rm cmdline-tools.zip
|
||||||
|
fi
|
||||||
|
|
||||||
|
export ANDROID_HOME="$SDK"
|
||||||
|
export ANDROID_SDK_ROOT="$SDK"
|
||||||
|
export PATH="$SDK/cmdline-tools/latest/bin:$PATH"
|
||||||
|
|
||||||
|
grep -q 'ANDROID_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" <<'EOF2'
|
||||||
|
|
||||||
|
# AndroidBuilder SDK environment
|
||||||
|
export ANDROID_HOME=$HOME/android-sdk
|
||||||
|
export ANDROID_SDK_ROOT=$ANDROID_HOME
|
||||||
|
export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$PATH
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
echo "==> Accepting Android SDK licenses"
|
||||||
|
mkdir -p "$SDK/licenses"
|
||||||
|
cat > "$SDK/licenses/android-sdk-license" <<'EOF2'
|
||||||
|
24333f8a63b6825ea9c5514f83c2829b004d1fee
|
||||||
|
d56f5187479451eabf01fb78af6dfcb131a6481e
|
||||||
|
8933bad161af4178b1185d1a37fbf41ea5269c55
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
echo "==> Installing SDK platform: $PLATFORM"
|
||||||
|
sdkmanager "platforms;$PLATFORM"
|
||||||
|
|
||||||
|
echo "==> Writing Gradle config"
|
||||||
|
mkdir -p "$HOME/.gradle"
|
||||||
|
cat > "$HOME/.gradle/gradle.properties" <<EOF2
|
||||||
|
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
|
||||||
|
org.gradle.daemon=true
|
||||||
|
org.gradle.parallel=true
|
||||||
|
org.gradle.caching=true
|
||||||
|
android.aapt2FromMavenOverride=$PREFIX/bin/aapt2
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Setup complete."
|
||||||
+173
@@ -0,0 +1,173 @@
|
|||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
AB_HOME="${ANDROID_BUILDER_HOME:-$HOME/android-builder}"
|
||||||
|
SDK="$HOME/android-sdk"
|
||||||
|
PLATFORM="${ANDROID_BUILDER_PLATFORM:-android-33}"
|
||||||
|
|
||||||
|
ensure_termux() {
|
||||||
|
if [ -z "${PREFIX:-}" ] || [ ! -d "/data/data/com.termux/files/usr" ]; then
|
||||||
|
echo "Error: this command must be run inside Termux."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_project_name() {
|
||||||
|
if [ -f settings.gradle ]; then
|
||||||
|
DETECTED_NAME="$(grep -E '^rootProject.name[[:space:]]*=' settings.gradle \
|
||||||
|
| sed -E 's/.*=[[:space:]]*["'\'']?([^"'\'' ]+)["'\'']?.*/\1/' \
|
||||||
|
| head -n 1)"
|
||||||
|
|
||||||
|
[ -n "$DETECTED_NAME" ] && echo "$DETECTED_NAME" && return
|
||||||
|
fi
|
||||||
|
|
||||||
|
basename "$PWD"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_build_type() {
|
||||||
|
echo "${ANDROID_BUILDER_BUILD_TYPE:-debug}"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_apk_path() {
|
||||||
|
case "$(get_build_type)" in
|
||||||
|
debug) echo "app/build/outputs/apk/debug/app-debug.apk" ;;
|
||||||
|
release) echo "app/build/outputs/apk/release/app-release.apk" ;;
|
||||||
|
*) return 1 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
create_base_project() {
|
||||||
|
NAME="$1"
|
||||||
|
MESSAGE="$2"
|
||||||
|
PACKAGE="com.example.$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9')"
|
||||||
|
PACKAGE_PATH="$(echo "$PACKAGE" | tr '.' '/')"
|
||||||
|
|
||||||
|
mkdir -p "$NAME/app/src/main/java/$PACKAGE_PATH"
|
||||||
|
mkdir -p "$NAME/app/src/main/res/values"
|
||||||
|
|
||||||
|
cat > "$NAME/settings.gradle" <<EOF2
|
||||||
|
pluginManagement { repositories { google(); mavenCentral(); gradlePluginPortal() } }
|
||||||
|
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS); repositories { google(); mavenCentral() } }
|
||||||
|
rootProject.name="$NAME"
|
||||||
|
include(":app")
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/build.gradle" <<'EOF2'
|
||||||
|
// Root build file intentionally minimal.
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/gradle.properties" <<EOF2
|
||||||
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||||
|
org.gradle.daemon=true
|
||||||
|
org.gradle.parallel=true
|
||||||
|
org.gradle.caching=true
|
||||||
|
android.aapt2FromMavenOverride=$PREFIX/bin/aapt2
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/local.properties" <<EOF2
|
||||||
|
sdk.dir=$SDK
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/app/build.gradle" <<EOF2
|
||||||
|
plugins {
|
||||||
|
id 'com.android.application' version '8.5.2'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace '$PACKAGE'
|
||||||
|
compileSdk 33
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "$PACKAGE"
|
||||||
|
minSdk 24
|
||||||
|
targetSdk 33
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/app/src/main/AndroidManifest.xml" <<'EOF2'
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<application
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
<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>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/app/src/main/res/values/strings.xml" <<EOF2
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">$NAME</string>
|
||||||
|
</resources>
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/app/src/main/res/values/styles.xml" <<'EOF2'
|
||||||
|
<resources>
|
||||||
|
<style name="AppTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
|
||||||
|
<item name="android:windowLightStatusBar">true</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/app/src/main/java/$PACKAGE_PATH/MainActivity.java" <<EOF2
|
||||||
|
package $PACKAGE;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
public class MainActivity extends Activity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
LinearLayout layout = new LinearLayout(this);
|
||||||
|
layout.setGravity(Gravity.CENTER);
|
||||||
|
layout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
layout.setPadding(32, 32, 32, 32);
|
||||||
|
|
||||||
|
TextView title = new TextView(this);
|
||||||
|
title.setText("$NAME");
|
||||||
|
title.setTextSize(30);
|
||||||
|
title.setGravity(Gravity.CENTER);
|
||||||
|
|
||||||
|
TextView message = new TextView(this);
|
||||||
|
message.setText("$MESSAGE");
|
||||||
|
message.setTextSize(18);
|
||||||
|
message.setGravity(Gravity.CENTER);
|
||||||
|
|
||||||
|
layout.addView(title);
|
||||||
|
layout.addView(message);
|
||||||
|
|
||||||
|
setContentView(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
cat > "$NAME/gradlew" <<'EOF2'
|
||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
exec gradle "$@"
|
||||||
|
EOF2
|
||||||
|
|
||||||
|
chmod +x "$NAME/gradlew"
|
||||||
|
|
||||||
|
echo "Created project: $NAME"
|
||||||
|
echo
|
||||||
|
echo "Next:"
|
||||||
|
echo " cd $NAME"
|
||||||
|
echo " android-builder build"
|
||||||
|
echo " android-builder export"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user