I'm currently working on a Flutter project and I tend to use VSCode, this is my configuration:
Json:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "UAT",
"request": "launch",
"type": "dart",
"program": "lib/main.dart",
"preLaunchTask": "UAT",
"args": [
"--target",
"lib/main.dart",
"--dart-define-from-file=env.json",
],
}
]
}
Which basically runs a task that has this command:
Json:
"command": "setup.sh uat",
Thing is that I'm trying to find a way for my colleges using AndroidStudio to get a similar experience by using the runConfigurations
in AndroidStudio
I have tried adding external tools, and it worked just fine... But you cannot add them to git because it's stored locally, so it refers to a tool u don't have
I also thought about adding it to build.gradle
, but I do not manage to get it working
Is there any advice u guys could give me?
Thanks! :)
I've created a script that takes the ".vscode/launch.json" and based on it (and the preLaunchTask it might have) it generates both ".idea/runConfigurations/[config].xml's" and some scripts, that get's added to my Makefile (if you use command line tool or want to run it from pipelines)
# Generate run configurations from launch.json
# Usage: ./generate.sh
# Colors
RESET='\033[0m'
SUCCESS='\033[0;32m'
WARN='\033[0;33m'
ERROR='\033[0;31m'
# Install jq if not installed
if ! command -v jq &>/dev/null; then
echo -e "${WARN}jq not found, installing...${RESET}"
# Try to install using brew
if command -v brew &>/dev/null; then
brew install jq
else
echo -e "${ERROR}brew not found, please install jq manually${RESET}"
exit 1
fi
fi
# Launch.json file
LAUNCH_JSON_FILE=".vscode/launch.json"
# Run configurations directory
RUN_CONFIGURATIONS_DIR=".idea/runConfigurations"
# Scripts directory
SCRIPTS_DIR="scripts/configs"
# Tasks.json file
TASKS_JSON_FILE=".vscode/tasks.json"
# Android Studio build.gradle file
ANDROID_GRADLE_FILE="android/scripts/build.gradle"
# Android settings.gradle file
ANDROID_SETTINGS_GRADLE="android/settings.gradle"
# Makefile path
MAKEFILE="Makefile"
# Check if launch.json file exists
if [ ! -f "$LAUNCH_JSON_FILE" ]; then
echo -e "${ERROR}$LAUNCH_JSON_FILE not found: ${RESET}"
exit 1
fi
# Check if tasks.json file exists
if [ ! -f "$TASKS_JSON_FILE" ]; then
echo -e "${WARN}$TASKS_JSON_FILE not found, preLaunchTasks will be ignored${RESET}"
fi
# Check if run configurations directory exists, if it does, cleanup, if not, create it
if [ ! -d "$RUN_CONFIGURATIONS_DIR" ]; then
echo -e "${WARN}$RUN_CONFIGURATIONS_DIR not found${RESET}"
echo -e "Creating run configurations directory..."
mkdir -p $RUN_CONFIGURATIONS_DIR
else
echo -e "Cleaning up run configurations directory..."
rm -rf $RUN_CONFIGURATIONS_DIR/*
fi
# Check if scripts directory exists, if not, create it
if [ ! -d "$SCRIPTS_DIR" ]; then
echo -e "${WARN}$SCRIPTS_DIR not found${RESET}"
echo -e "Creating scripts directory..."
mkdir -p $SCRIPTS_DIR
else
echo -e "Cleaning up scripts directory..."
rm -rf $SCRIPTS_DIR/*
fi
# Ensure the directory for build.gradle exists
mkdir -p $(dirname $ANDROID_GRADLE_FILE)
# Initialize build.gradle content
echo "" >$ANDROID_GRADLE_FILE
# Function to get task command
get_task_command() {
local task_label=$1
jq -r ".tasks[] | select(.label == \"$task_label\") | .command" $TASKS_JSON_FILE
}
# Function to clean empty lines at the end of a file
clean_empty_lines() {
local file=$1
# Remove empty lines at the end of the file
sed -i '' -e :a -e '/^\n*$/{$d;N;ba' -e '}' "$file"
# Add a newline at the end of the file
echo >>"$file"
}
# Function to update Makefile
update_makefile() {
local environments=""
local makefile_content=""
# Extract unique environment names from configurations
while read -r CONFIGURATION; do
ENV_NAME=$(echo $CONFIGURATION | jq -r '.name' | cut -d ' ' -f1)
if [[ ! $environments =~ $ENV_NAME ]]; then
environments+="$ENV_NAME "
fi
done <<<"$CONFIGURATIONS"
# Generate Makefile content
makefile_content=$(
cat <<EOF
# Environment targets | ⚠️ DO NOT ADD ANYTHING BELOW THIS LINE
.PHONY: $(echo $environments | tr '[:upper:]' '[:lower:]')
$(for env in $environments; do
env_lower=$(echo $env | tr '[:upper:]' '[:lower:]')
echo "$env_lower: ## Build/Run for $env environment. Use 'make $env_lower [args=\"build|run [additional args]\"]'"
done)
$(echo $environments | tr '[:upper:]' '[:lower:]'):
@if [ -z "\$(args)" ]; then \\
./scripts/configs/\$(shell printf '%s' "\$@" | tr '[:lower:]' '[:upper:]').sh run; \\
else \\
./scripts/configs/\$(shell printf '%s' "\$@" | tr '[:lower:]' '[:upper:]').sh \$(args); \\
fi
EOF
)
# Update Makefile
if [ -f "$MAKEFILE" ]; then
# Remove existing environment targets section
sed -i '' '/^# Environment targets | ⚠️ DO NOT ADD ANYTHING BELOW THIS LINE/,/^$/d' "$MAKEFILE"
# Append new environment targets
echo "$makefile_content" >>"$MAKEFILE"
echo -e "${SUCCESS}Updated Makefile with new environment targets${RESET}"
else
echo -e "${WARN}Makefile not found. Creating a new one with environment targets${RESET}"
echo "$makefile_content" >"$MAKEFILE"
fi
}
# Get configurations from launch.json
CONFIGURATIONS=$(jq -c '.configurations[]' $LAUNCH_JSON_FILE)
echo "Generating run configurations..."
HAS_PRE_LAUNCH_TASKS=false
# Iterate over configurations
while read -r CONFIGURATION; do
# Get configuration name
CONFIGURATION_NAME=$(echo $CONFIGURATION | jq -r '.name')
# Get configuration program
CONFIGURATION_PROGRAM=$(echo $CONFIGURATION | jq -r '.program')
# Get configuration args
CONFIGURATION_ARGS=$(echo $CONFIGURATION | jq -r '.args | join(" ")')
# Get preLaunchTask if it exists
PRE_LAUNCH_TASK=$(echo $CONFIGURATION | jq -r '.preLaunchTask // empty')
# Create run configuration file
cat <<EOF >$RUN_CONFIGURATIONS_DIR/$CONFIGURATION_NAME.xml
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="$CONFIGURATION_NAME" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="additionalArgs" value="$CONFIGURATION_ARGS" />
<option name="filePath" value="\$PROJECT_DIR\$/$CONFIGURATION_PROGRAM" />
<method v="2">
EOF
# Add Gradle task if preLaunchTask exists
if [ -n "$PRE_LAUNCH_TASK" ]; then
HAS_PRE_LAUNCH_TASKS=true
TASK_COMMAND=$(get_task_command "$PRE_LAUNCH_TASK")
if [ -n "$TASK_COMMAND" ]; then
echo " <option name=\"Gradle.BeforeRunTask\" enabled=\"true\" tasks=\"$CONFIGURATION_NAME\" externalProjectPath=\"\$PROJECT_DIR\$/android/scripts\" vmOptions=\"\" scriptParameters=\"\" />" >>$RUN_CONFIGURATIONS_DIR/$CONFIGURATION_NAME.xml
# Add task to build.gradle
cat <<EOF >>$ANDROID_GRADLE_FILE
task $CONFIGURATION_NAME(type: Exec) {
workingDir "../../"
commandLine 'bash', '-c', '$TASK_COMMAND'
}
EOF
fi
fi
echo " </method>" >>$RUN_CONFIGURATIONS_DIR/$CONFIGURATION_NAME.xml
echo " </configuration>" >>$RUN_CONFIGURATIONS_DIR/$CONFIGURATION_NAME.xml
echo "</component>" >>$RUN_CONFIGURATIONS_DIR/$CONFIGURATION_NAME.xml
# Create script file for running the configuration
SCRIPT_FILE="$SCRIPTS_DIR/$CONFIGURATION_NAME.sh"
cat <<EOF >$SCRIPT_FILE
#!/bin/bash
# Usage: ./$CONFIGURATION_NAME.sh [run|build] [additional build args...]
# If no action is provided, it defaults to 'run'
# For 'build', additional arguments can be provided (e.g., ios --no-codesign, aab, etc.)
ACTION=\${1:-run}
# Add preLaunchTask command if it exists
if [ -n "$PRE_LAUNCH_TASK" ]; then
TASK_COMMAND="$(get_task_command "$PRE_LAUNCH_TASK")"
if [ -n "\$TASK_COMMAND" ]; then
\$TASK_COMMAND
fi
fi
if [ "\$ACTION" = "run" ]; then
flutter run $CONFIGURATION_ARGS --target=$CONFIGURATION_PROGRAM
elif [ "\$ACTION" = "build" ]; then
shift 1 # Remove action argument
flutter build \$@ $CONFIGURATION_ARGS --target=$CONFIGURATION_PROGRAM
else
echo "Invalid action. Use 'run' or 'build'."
exit 1
fi
EOF
chmod +x $SCRIPT_FILE
echo -e "${SUCCESS}Generated $CONFIGURATION_NAME${RESET}"
done <<<"$CONFIGURATIONS"
# Check if there are any preLaunchTasks
if [ "$HAS_PRE_LAUNCH_TASKS" = false ]; then
echo "No preLaunchTasks found. Removing $ANDROID_GRADLE_FILE..."
rm -f $ANDROID_GRADLE_FILE
# Remove include ":scripts" from settings.gradle if it exists
if [ -f "$ANDROID_SETTINGS_GRADLE" ]; then
sed -i '' '/include ":scripts"/d' "$ANDROID_SETTINGS_GRADLE"
echo "Removed 'include \":scripts\"' from settings.gradle"
clean_empty_lines "$ANDROID_SETTINGS_GRADLE"
fi
else
echo "PreLaunchTasks found. Keeping $ANDROID_GRADLE_FILE..."
# Update settings.gradle
if [ -f "$ANDROID_SETTINGS_GRADLE" ]; then
if ! grep -q "include \":scripts\"" "$ANDROID_SETTINGS_GRADLE"; then
echo "Updating $ANDROID_SETTINGS_GRADLE..."
echo "include \":scripts\"" >>"$ANDROID_SETTINGS_GRADLE"
fi
clean_empty_lines "$ANDROID_SETTINGS_GRADLE"
else
echo -e "${WARN}$ANDROID_SETTINGS_GRADLE not found${RESET}"
fi
fi
update_makefile
# Check if git is installed, if not, print a warning otherwise add run configurations and scripts to git
if ! command -v git &>/dev/null; then
echo -e "${WARN}git not found, please install git, or manually add $RUN_CONFIGURATIONS_DIR and $SCRIPTS_DIR to git${RESET}"
else
echo "Adding run configurations and scripts to git..."
git add -f $RUN_CONFIGURATIONS_DIR $SCRIPTS_DIR $MAKEFILE
if [ -f "$ANDROID_GRADLE_FILE" ]; then
git add -f $ANDROID_GRADLE_FILE
fi
if [ -f "$ANDROID_SETTINGS_GRADLE" ]; then
git add -f $ANDROID_SETTINGS_GRADLE
fi
fi
# Done
echo -e "${SUCCESS}Done!${RESET}"
exit 0