Skip to content

Instantly share code, notes, and snippets.

@lopesivan
Created July 17, 2026 19:38
Show Gist options
  • Select an option

  • Save lopesivan/965447321c7d477b1bf4abf1a7c60cda to your computer and use it in GitHub Desktop.

Select an option

Save lopesivan/965447321c7d477b1bf4abf1a7c60cda to your computer and use it in GitHub Desktop.
Ferramentas de criacao de projeteto android 4.4.2
ANDROID_PLATFORM=android-19
ANDROID_HOME=/home/ivan/Android/api/16/android-sdk-linux
PATH={PATH}:{ANDROID_HOME}/tools:{ANDROID_HOME}/platform-tools
#!/usr/bin/env bash
set -e
set -u
set -o pipefail
# Verificar se ANDROID_HOME está definido
[ "${ANDROID_HOME:-}" ] || {
dialog --msgbox "❌ ERRO: Defina a variável \$ANDROID_HOME
💡 Exemplo:
export ANDROID_HOME=/home/ivan/Android/api/16/android-sdk-linux" 11 72
exit 2
}
# Configurações padrão
DEFAULT_TARGET="$(android list targets | grep ${ANDROID_PLATFORM} | awk '{print $2}')"
DEFAULT_NAME="MyApp"
DEFAULT_ACTIVITY="MainActivity"
DEFAULT_PACKAGE="br.eng.ivanlopes.myapp"
DEFAULT_PATH="$PWD"
# Verificar dependências
check_dependencies() {
local missing_deps=()
if ! command -v dialog &>/dev/null; then
missing_deps+=("dialog")
fi
if ! command -v android &>/dev/null; then
dialog --msgbox "❌ ERRO: Comando 'android' não encontrado!
🧰 Verifique se \$ANDROID_HOME/tools está no \$PATH
📦 ANDROID_HOME atual:
$ANDROID_HOME" 13 72
exit 1
fi
if [ ${#missing_deps[@]} -ne 0 ]; then
echo "❌ Dependências não encontradas: ${missing_deps[*]}"
echo "💡 Instale com: sudo apt install ${missing_deps[*]}"
exit 1
fi
}
# Listar targets disponíveis em pares compatíveis com dialog --menu
get_targets() {
local -a result=()
while IFS= read -r line; do
result+=("$line")
done < <(android list targets 2>/dev/null | awk '
/^id:/ {
if (id != "") { print id; print name " (API " api ")" }
id = $2; name = ""; api = ""
next
}
/Name:/ { sub(/^[ ]*Name: */, ""); name = $0 }
/API level:/ { sub(/^[ ]*API level: */, ""); api = $0 }
END { if (id != "") { print id; print name " (API " api ")" } }
')
printf '%s
' "${result[@]}"
}
# Validar nome do projeto
validate_project_name() {
local name="$1"
[[ "$name" =~ ^[A-Za-z][A-Za-z0-9_]*$ ]]
}
# Validar package name
validate_package_name() {
local package="$1"
[[ "$package" =~ ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$ ]]
}
# Validar activity name
validate_activity_name() {
local activity="$1"
[[ "$activity" =~ ^[A-Z][A-Za-z0-9_]*$ ]]
}
# Menu principal
main_menu() {
local choice
while true; do
choice=$(dialog --backtitle "🤖 Criador de Projetos Android v1.0" --title "⚙️ Menu Principal" --menu "Escolha uma opção:" 18 72 10 1 "🤖 Configurar target Android ($target)" 2 "📦 Nome do projeto ($project_name)" 3 "📁 Diretório base ($base_path)" 4 "🖥️ Activity principal ($activity_name)" 5 "📛 Package name ($package_name)" 6 "📋 Listar targets disponíveis" 7 "⚙️ Visualizar configurações" 8 "🚀 Criar projeto" 9 "🚪 Sair" 2>&1 >/dev/tty) || exit 0
case "$choice" in
1) configure_target ;;
2) configure_project_name ;;
3) configure_base_path ;;
4) configure_activity ;;
5) configure_package ;;
6) list_targets ;;
7) show_config ;;
8) create_project ;;
9) exit 0 ;;
*) exit 0 ;;
esac
done
}
# Configurar target
configure_target() {
local -a targets_list=()
local selected_target
while IFS= read -r line; do
targets_list+=("$line")
done < <(get_targets)
if [ ${#targets_list[@]} -eq 0 ]; then
dialog --msgbox "❌ ERRO: Não foi possível obter a lista de targets.
🧰 Verifique sua instalação do Android SDK." 9 62
return
fi
selected_target=$(dialog --title "🤖 Target Android" --menu "Escolha o target Android:" 20 82 10 "${targets_list[@]}" 2>&1 >/dev/tty) || return
if [ -n "$selected_target" ]; then
target="$selected_target"
else
target="$DEFAULT_TARGET"
fi
}
# Configurar nome do projeto
configure_project_name() {
local input_name
while true; do
input_name=$(dialog --title "📦 Nome do Projeto" --inputbox "Digite o nome do projeto:" 8 54 "$project_name" 2>&1 >/dev/tty) || return
if [ -z "$input_name" ]; then
input_name="$DEFAULT_NAME"
fi
if validate_project_name "$input_name"; then
project_name="$input_name"
break
fi
dialog --msgbox "❌ ERRO: Nome inválido!
O nome deve:
• Começar com letra
• Conter apenas letras, números e _
• Não ter espaços" 11 54
done
}
# Configurar diretório base
configure_base_path() {
local selected_path
selected_path=$(dialog --title "📁 Diretório Base" --dselect "$base_path/" 20 62 2>&1 >/dev/tty) || return
if [ -z "$selected_path" ]; then
return
fi
base_path="$selected_path"
if [ ! -d "$base_path" ]; then
dialog --yesno "📁 Diretório não existe.
Criar agora?
$base_path" 10 62
if [ $? -eq 0 ]; then
mkdir -p "$base_path" || {
dialog --msgbox "❌ ERRO: Não foi possível criar o diretório." 8 54
base_path="$DEFAULT_PATH"
}
else
base_path="$DEFAULT_PATH"
fi
fi
}
# Configurar activity
configure_activity() {
local input_activity
while true; do
input_activity=$(dialog --title "🖥️ Activity Principal" --inputbox "Digite o nome da Activity principal:" 8 56 "$activity_name" 2>&1 >/dev/tty) || return
if [ -z "$input_activity" ]; then
input_activity="$DEFAULT_ACTIVITY"
fi
if validate_activity_name "$input_activity"; then
activity_name="$input_activity"
break
fi
dialog --msgbox "❌ ERRO: Nome de Activity inválido!
O nome deve:
• Começar com letra maiúscula
• Conter apenas letras, números e _
• Seguir convenção PascalCase" 11 58
done
}
# Configurar package
configure_package() {
local input_package
while true; do
input_package=$(dialog --title "📛 Package Name" --inputbox "Digite o package name:" 8 56 "$package_name" 2>&1 >/dev/tty) || return
if [ -z "$input_package" ]; then
input_package="$DEFAULT_PACKAGE"
fi
if validate_package_name "$input_package"; then
package_name="$input_package"
break
fi
dialog --msgbox "❌ ERRO: Package name inválido!
Formato esperado:
com.empresa.app
• Apenas letras minúsculas e números
• Separado por pontos
• Cada parte deve começar com letra" 13 60
done
}
# Listar targets
list_targets() {
local tmpfile
tmpfile=$(mktemp)
android list targets >"$tmpfile" 2>&1 || true
dialog --title "📋 Targets Android Disponíveis" --textbox "$tmpfile" 22 84
rm -f "$tmpfile"
}
# Mostrar configurações
show_config() {
local project_path="$base_path/$project_name"
dialog --msgbox "⚙️ CONFIGURAÇÕES ATUAIS
🤖 Target: $target
📦 Nome do Projeto: $project_name
📁 Diretório Base: $base_path
📁 Caminho Completo: $project_path
🖥️ Activity Principal: $activity_name
📛 Package Name: $package_name
🧰 ANDROID_HOME: $ANDROID_HOME
🚀 Comando que será executado:
android create project \
--target $target \
--name $project_name \
--path $project_path \
--activity $activity_name \
--package $package_name" 20 76
}
# Criar projeto debug
create_project() {
local project_path="$base_path/$project_name"
if [ -d "$project_path" ]; then
dialog --yesno "⚠️ O diretório já existe!
$project_path
Continuar mesmo assim?" 10 64
if [ $? -ne 0 ]; then
return
fi
fi
dialog --yesno "🚀 Criar projeto Android?
🤖 Target: $target
📦 Nome: $project_name
📁 Path: $project_path
🖥️ Activity: $activity_name
📛 Package: $package_name" 14 66
if [ $? -ne 0 ]; then
return
fi
(
echo "🚀 Criando projeto Android..."
android create project --target "$target" --name "$project_name" --path "$project_path" --activity "$activity_name" --package "$package_name" 2>&1
echo "✅ DONE"
) | dialog --title "🚀 Criando Projeto" --programbox "Criando projeto Android..." 16 72
if [ ${PIPESTATUS[0]} -eq 0 ]; then
cat <<'EOF' >"$project_path/.classpath"
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry
kind="lib"
path="/home/ivan/Android/16/android-sdk-linux/platforms/${ANDROID_PLATFORM}/android.jar"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
EOF
cat <<'EOF' >"$project_path/.project"
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyApp</name>
<comment>Projeto Android legado API 16 baseado em Ant</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
EOF
cat <<'EOF' >"$project_path/Makefile"
#===============================================================================
# Projeto Android legado - API 16 / Android 4.1
#===============================================================================
#-------------------------------------------------------------------------------
# Dispositivo
#-------------------------------------------------------------------------------
HOST := 192.168.2.101
PORT := 5555
DEVICE := $(HOST):$(PORT)
ADB_SELECTED_DEVICE := $(HOST):$(PORT)
#-------------------------------------------------------------------------------
# Caminhos principais
#-------------------------------------------------------------------------------
ANDROID_HOME := /home/ivan/Android/api/16/android-sdk-linux
JAVA_HOME := /home/ivan/.jenv/versions/1.8
LINUXBREW_HOME := /home/linuxbrew/.linuxbrew
ANDROID_TOOLS := $(ANDROID_HOME)/tools
ANDROID_PLATFORM_TOOLS := $(ANDROID_HOME)/platform-tools
#-------------------------------------------------------------------------------
# Ambiente exportado para Ant, adb e ferramentas Android antigas
#-------------------------------------------------------------------------------
export ANDROID_HOME
export JAVA_HOME
export ANDROID_SERIAL := $(DEVICE)
export PATH := $(JAVA_HOME)/bin:$(ANDROID_TOOLS):$(ANDROID_PLATFORM_TOOLS):$(PATH)
#-------------------------------------------------------------------------------
# Programas
#-------------------------------------------------------------------------------
ANT := JAVA_HOME=$(JAVA_HOME) PATH=$(JAVA_HOME)/bin:$(ANDROID_TOOLS):$(ANDROID_PLATFORM_TOOLS):$(PATH) /usr/bin/ant
JENV := $(LINUXBREW_HOME)/bin/jenv
XMLSTARLET := xmlstarlet
ifdef ADB_SELECTED_DEVICE
ADB := $(ANDROID_PLATFORM_TOOLS)/adb -s $(ADB_SELECTED_DEVICE)
else
ADB := $(ANDROID_PLATFORM_TOOLS)/adb
endif
ADB_SHELL := $(ADB) shell
INPUT := $(ADB_SHELL) input
KEYEVENT := $(INPUT) keyevent
#-------------------------------------------------------------------------------
# Informações do projeto Android
#-------------------------------------------------------------------------------
PACKAGE := $(shell xmlstarlet select -T -t -v "//manifest/@package" -n AndroidManifest.xml)
MAINACTIVITY := $(PACKAGE).$(shell xmlstarlet select -T -t -v "//application/activity/@android:name" -n AndroidManifest.xml)
#-------------------------------------------------------------------------------
# Alvos
#-------------------------------------------------------------------------------
.PHONY: \
status \
connect \
disconnect \
fix-java-version \
build \
install \
uninstall \
stop \
run \
deploy \
clean
#-------------------------------------------------------------------------------
# Diagnóstico
#-------------------------------------------------------------------------------
status:
@echo "ANDROID_SERIAL=$(ANDROID_SERIAL)"
@echo "ANDROID_HOME=$(ANDROID_HOME)"
@echo "JAVA_HOME=$(JAVA_HOME)"
@echo "PACKAGE=$(PACKAGE)"
@echo "MAINACTIVITY=$(MAINACTIVITY)"
@java -version
@javac -version
@$(ANT) -diagnostics | grep -E "java.home|java.version|ant.java.version"
@$(ANT) -version
@$(JENV) version || true
@$(ADB) devices
#-------------------------------------------------------------------------------
# Configuração exigida pelo Ant antigo usando javac moderno
#-------------------------------------------------------------------------------
fix-java-version:
@echo "java.source=1.8" > ant.properties
@echo "java.target=1.8" >> ant.properties
#-------------------------------------------------------------------------------
# Dispositivo
#-------------------------------------------------------------------------------
connect:
@$(ADB) connect $(DEVICE)
disconnect:
@$(ADB) disconnect $(DEVICE)
#-------------------------------------------------------------------------------
# Build / deploy
#-------------------------------------------------------------------------------
build: fix-java-version
@$(ANT) debug
install:
@$(ANT) installd
uninstall:
@$(ADB) uninstall $(PACKAGE)
run:
@$(ADB) shell am start -n $(PACKAGE)/$(MAINACTIVITY)
stop:
@$(ADB) shell am force-stop $(PACKAGE)
deploy: uninstall build install run
clean:
@$(ANT) clean
#-------------------------------------------------------------------------------
# Ferramentas extras do projeto
#-------------------------------------------------------------------------------
include tools/tools.mk
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
.PHONY: list
list:
@LC_ALL=C $(MAKE) -pRrq -f $(firstword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$'
# IMPORTANT: The line above must be indented by (at least one)
# *actual TAB character* - *spaces* do *not* work.
EOF
mkdir -p "$project_path/tools"
cat <<'EOF' >"$project_path/tools/tools.mk"
.PHONY: \
screenshot \
screen.png \
shell \
show \
version \
home \
back \
menu \
ok \
assist \
devices \
notification \
profile-switch \
recents \
refresh \
search \
all-apps \
settings \
voice-assist
screenshot: ## Salva uma captura de tela
@echo "📸 Capturando tela..."
@$(ADB) exec-out screencap -p > screen.png 2>/dev/null || { \
$(ADB) shell screencap -p /sdcard/screen.png; \
$(ADB) pull /sdcard/screen.png screen.png >/dev/null; \
$(ADB) shell rm /sdcard/screen.png >/dev/null; \
}
@echo "✅ screen.png criada"
show: screen.png
eog screen.png
version:
@$(ADB) shell cat /proc/version
devices: ## lista dispositivos conectados via ADB
$(ADB) devices
shell: ## abre shell ADB
$(ADB) shell
# =============================================================================
# Navegação principal
# =============================================================================
back: ## envia botão voltar
$(KEYEVENT) KEYCODE_BACK
home: ## envia botão home
$(KEYEVENT) KEYCODE_HOME
menu: ## envia botão menu
$(KEYEVENT) KEYCODE_MENU
ok: ## envia botão OK (dpad center)
$(KEYEVENT) KEYCODE_DPAD_CENTER
recents: ## abre apps recentes
$(KEYEVENT) KEYCODE_APP_SWITCH
search: ## abre busca
$(KEYEVENT) KEYCODE_SEARCH
assist: ## abre assistente (API 19)
$(KEYEVENT) KEYCODE_ASSIST
voice-assist: ## assistente de voz (API 21)
$(KEYEVENT) KEYCODE_VOICE_ASSIST
all-apps: ## todos os apps (API 28)
$(KEYEVENT) KEYCODE_ALL_APPS
refresh: ## atualiza (API 28)
$(KEYEVENT) KEYCODE_REFRESH
# help: ## abre ajuda (API 23)
# $(KEYEVENT) KEYCODE_HELP
settings: ## abre configurações
$(KEYEVENT) KEYCODE_SETTINGS
notification: ## abre notificações
$(KEYEVENT) KEYCODE_NOTIFICATION
profile-switch: ## troca perfil (API 29)
$(KEYEVENT) KEYCODE_PROFILE_SWITCH
# =============================================================================
# Obtém o estado atual: 1 = tela apagada, 2 = tela acesa
# =============================================================================
define screen_state
$(shell $(ADB) shell dumpsys display | grep "mAllDisplayBlankStateFromPowerManager" | cut -d= -f2 )
endef
.PHONY: on-screen off-screen onoff-screen
# Liga a tela (se apagada)
on-screen:
@if [ "$(screen_state)" = "1" ]; then \
echo "Tela apagada -> ligando..."; \
$(ADB) shell input keyevent 26; \
else \
echo "Tela já está acesa."; \
fi
# Apaga a tela (se acesa)
off-screen:
@if [ "$(screen_state)" = "2" ]; then \
echo "Tela acesa -> apagando..."; \
$(ADB) shell input keyevent 26; \
else \
echo "Tela já está apagada."; \
fi
onoff-screen:
$(ADB) shell input keyevent KEYCODE_POWER
EOF
dialog --msgbox "✅ Projeto criado com sucesso!
📁 Localização:
$project_path
🔨 Para compilar:
cd $project_path
make build" 12 66
dialog --yesno "📂 Abrir o diretório do projeto no gerenciador de arquivos?" 8 58
if [ $? -eq 0 ]; then
if command -v nautilus &>/dev/null; then
nautilus "$project_path" &
elif command -v dolphin &>/dev/null; then
dolphin "$project_path" &
elif command -v thunar &>/dev/null; then
thunar "$project_path" &
else
dialog --msgbox "⚠️ Nenhum gerenciador conhecido encontrado.
📁 Projeto em:
$project_path" 10 62
fi
fi
else
dialog --msgbox "❌ ERRO: Falha ao criar projeto!
Verifique:
• Se o target existe
• Se há permissões no diretório
• Se o Android SDK está configurado" 11 64
fi
}
# Inicialização
check_dependencies
target="$DEFAULT_TARGET"
project_name="$DEFAULT_NAME"
base_path="$DEFAULT_PATH"
activity_name="$DEFAULT_ACTIVITY"
package_name="$DEFAULT_PACKAGE"
dialog --msgbox "🤖 Criador de Projetos Android
📦 ANDROID_HOME:
$ANDROID_HOME
🧰 PATH SDK:
$(echo "$PATH" | grep -o "$ANDROID_HOME[^:]*" | head -1)
Pressione ENTER para continuar..." 13 74
main_menu
exit 0
#!/usr/bin/env bash
set -e
set -u
set -o pipefail
SCRIPT_KEY_STORE_FILE="meu-release-key.keystore"
SCRIPT_KEY_ALIAS="minha-chave"
SCRIPT_KEY_STORE_PASSWORD="senha123"
SCRIPT_KEY_ALIAS_PASSWORD="senha123"
SCRIPT_JAVA="1.7"
# Verificar se ANDROID_HOME está definido
[ "${ANDROID_HOME:-}" ] || {
dialog --msgbox "❌ ERRO: Defina a variável \$ANDROID_HOME
💡 Exemplo:
export ANDROID_HOME=/home/ivan/Android/api/16/android-sdk-linux" 11 72
exit 2
}
# Configurações padrão
DEFAULT_TARGET="$(android list targets | grep ${ANDROID_PLATFORM} | awk '{print $2}')"
DEFAULT_NAME="MyApp"
DEFAULT_ACTIVITY="MainActivity"
DEFAULT_PACKAGE="br.eng.ivanlopes.myapp"
DEFAULT_PATH="$PWD"
# Verificar dependências
check_dependencies() {
local missing_deps=()
if ! command -v dialog &>/dev/null; then
missing_deps+=("dialog")
fi
if ! command -v android &>/dev/null; then
dialog --msgbox "❌ ERRO: Comando 'android' não encontrado!
🧰 Verifique se \$ANDROID_HOME/tools está no \$PATH
📦 ANDROID_HOME atual:
$ANDROID_HOME" 13 72
exit 1
fi
if [ ${#missing_deps[@]} -ne 0 ]; then
echo "❌ Dependências não encontradas: ${missing_deps[*]}"
echo "💡 Instale com: sudo apt install ${missing_deps[*]}"
exit 1
fi
}
# Listar targets disponíveis em pares compatíveis com dialog --menu
get_targets() {
local -a result=()
while IFS= read -r line; do
result+=("$line")
done < <(android list targets 2>/dev/null | awk '
/^id:/ {
if (id != "") { print id; print name " (API " api ")" }
id = $2; name = ""; api = ""
next
}
/Name:/ { sub(/^[ ]*Name: */, ""); name = $0 }
/API level:/ { sub(/^[ ]*API level: */, ""); api = $0 }
END { if (id != "") { print id; print name " (API " api ")" } }
')
printf '%s
' "${result[@]}"
}
# Validar nome do projeto
validate_project_name() {
local name="$1"
[[ "$name" =~ ^[A-Za-z][A-Za-z0-9_]*$ ]]
}
# Validar package name
validate_package_name() {
local package="$1"
[[ "$package" =~ ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$ ]]
}
# Validar activity name
validate_activity_name() {
local activity="$1"
[[ "$activity" =~ ^[A-Z][A-Za-z0-9_]*$ ]]
}
# Menu principal
main_menu() {
local choice
while true; do
choice=$(dialog --backtitle "🤖 Criador de Projetos Android v1.0" --title "⚙️ Menu Principal" --menu "Escolha uma opção:" 18 72 10 1 "🤖 Configurar target Android ($target)" 2 "📦 Nome do projeto ($project_name)" 3 "📁 Diretório base ($base_path)" 4 "🖥️ Activity principal ($activity_name)" 5 "📛 Package name ($package_name)" 6 "📋 Listar targets disponíveis" 7 "⚙️ Visualizar configurações" 8 "🚀 Criar projeto" 9 "🚪 Sair" 2>&1 >/dev/tty) || exit 0
case "$choice" in
1) configure_target ;;
2) configure_project_name ;;
3) configure_base_path ;;
4) configure_activity ;;
5) configure_package ;;
6) list_targets ;;
7) show_config ;;
8) create_project ;;
9) exit 0 ;;
*) exit 0 ;;
esac
done
}
# Configurar target
configure_target() {
local -a targets_list=()
local selected_target
while IFS= read -r line; do
targets_list+=("$line")
done < <(get_targets)
if [ ${#targets_list[@]} -eq 0 ]; then
dialog --msgbox "❌ ERRO: Não foi possível obter a lista de targets.
🧰 Verifique sua instalação do Android SDK." 9 62
return
fi
selected_target=$(dialog --title "🤖 Target Android" --menu "Escolha o target Android:" 20 82 10 "${targets_list[@]}" 2>&1 >/dev/tty) || return
if [ -n "$selected_target" ]; then
target="$selected_target"
else
target="$DEFAULT_TARGET"
fi
}
# Configurar nome do projeto
configure_project_name() {
local input_name
while true; do
input_name=$(dialog --title "📦 Nome do Projeto" --inputbox "Digite o nome do projeto:" 8 54 "$project_name" 2>&1 >/dev/tty) || return
if [ -z "$input_name" ]; then
input_name="$DEFAULT_NAME"
fi
if validate_project_name "$input_name"; then
project_name="$input_name"
break
fi
dialog --msgbox "❌ ERRO: Nome inválido!
O nome deve:
• Começar com letra
• Conter apenas letras, números e _
• Não ter espaços" 11 54
done
}
# Configurar diretório base
configure_base_path() {
local selected_path
selected_path=$(dialog --title "📁 Diretório Base" --dselect "$base_path/" 20 62 2>&1 >/dev/tty) || return
if [ -z "$selected_path" ]; then
return
fi
base_path="$selected_path"
if [ ! -d "$base_path" ]; then
dialog --yesno "📁 Diretório não existe.
Criar agora?
$base_path" 10 62
if [ $? -eq 0 ]; then
mkdir -p "$base_path" || {
dialog --msgbox "❌ ERRO: Não foi possível criar o diretório." 8 54
base_path="$DEFAULT_PATH"
}
else
base_path="$DEFAULT_PATH"
fi
fi
}
# Configurar activity
configure_activity() {
local input_activity
while true; do
input_activity=$(dialog --title "🖥️ Activity Principal" --inputbox "Digite o nome da Activity principal:" 8 56 "$activity_name" 2>&1 >/dev/tty) || return
if [ -z "$input_activity" ]; then
input_activity="$DEFAULT_ACTIVITY"
fi
if validate_activity_name "$input_activity"; then
activity_name="$input_activity"
break
fi
dialog --msgbox "❌ ERRO: Nome de Activity inválido!
O nome deve:
• Começar com letra maiúscula
• Conter apenas letras, números e _
• Seguir convenção PascalCase" 11 58
done
}
# Configurar package
configure_package() {
local input_package
while true; do
input_package=$(dialog --title "📛 Package Name" --inputbox "Digite o package name:" 8 56 "$package_name" 2>&1 >/dev/tty) || return
if [ -z "$input_package" ]; then
input_package="$DEFAULT_PACKAGE"
fi
if validate_package_name "$input_package"; then
package_name="$input_package"
break
fi
dialog --msgbox "❌ ERRO: Package name inválido!
Formato esperado:
com.empresa.app
• Apenas letras minúsculas e números
• Separado por pontos
• Cada parte deve começar com letra" 13 60
done
}
# Listar targets
list_targets() {
local tmpfile
tmpfile=$(mktemp)
android list targets >"$tmpfile" 2>&1 || true
dialog --title "📋 Targets Android Disponíveis" --textbox "$tmpfile" 22 84
rm -f "$tmpfile"
}
# Mostrar configurações
show_config() {
local project_path="$base_path/$project_name"
dialog --msgbox "⚙️ CONFIGURAÇÕES ATUAIS
🤖 Target: $target
📦 Nome do Projeto: $project_name
📁 Diretório Base: $base_path
📁 Caminho Completo: $project_path
🖥️ Activity Principal: $activity_name
📛 Package Name: $package_name
🧰 ANDROID_HOME: $ANDROID_HOME
🚀 Comando que será executado:
android create project \
--target $target \
--name $project_name \
--path $project_path \
--activity $activity_name \
--package $package_name" 20 76
}
# Criar projeto release
create_project() {
local project_path="$base_path/$project_name"
if [ -d "$project_path" ]; then
dialog --yesno "⚠️ O diretório já existe!
$project_path
Continuar mesmo assim?" 10 64
if [ $? -ne 0 ]; then
return
fi
fi
dialog --yesno "🚀 Criar projeto Android com suporte a release?
🤖 Target: $target
📦 Nome: $project_name
📁 Path: $project_path
🖥️ Activity: $activity_name
📛 Package: $package_name
🔐 Keystore: .keystore/$SCRIPT_KEY_STORE_FILE" 16 70
if [ $? -ne 0 ]; then
return
fi
(
echo "🚀 Criando projeto Android..."
android create project --target "$target" --name "$project_name" --path "$project_path" --activity "$activity_name" --package "$package_name" 2>&1
echo "✅ DONE"
) | dialog --title "🚀 Criando Projeto" --programbox "Criando projeto Android..." 16 72
if [ ${PIPESTATUS[0]} -ne 0 ]; then
dialog --msgbox "❌ ERRO: Falha ao criar projeto!
Verifique:
• Se o target existe
• Se há permissões no diretório
• Se o Android SDK está configurado" 11 64
return
fi
cat <<'EOF' >"$project_path/build.xml"
<?xml version="1.0" encoding="UTF-8"?>
<project name="AndroidProject" default="help">
<property file="local.properties" />
<property file="ant.properties" />
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<loadproperties srcFile="project.properties" />
<fail
message="sdk.dir is missing. Generate local.properties with 'android update project' or export ANDROID_HOME."
unless="sdk.dir"
/>
<import file="custom_rules.xml" optional="true" />
<!-- version-tag: custom -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>
EOF
cat <<EOF >"$project_path/ant.properties"
# Configurações Ant para build release assinado.
key.store=.keystore/$SCRIPT_KEY_STORE_FILE
key.alias=$SCRIPT_KEY_ALIAS
key.store.password=$SCRIPT_KEY_STORE_PASSWORD
key.alias.password=$SCRIPT_KEY_ALIAS_PASSWORD
java.source=$SCRIPT_JAVA
java.target=$SCRIPT_JAVA
EOF
cat <<EOF >"$project_path/key.sh"
#!/usr/bin/env bash
set -e
set -u
set -o pipefail
KEYSTORE_DIR=".keystore"
KEYSTORE_FILE="\$KEYSTORE_DIR/$SCRIPT_KEY_STORE_FILE"
ALIAS="$SCRIPT_KEY_ALIAS"
KEYSTORE_PASS="\${KEYSTORE_PASS:-$SCRIPT_KEY_STORE_PASSWORD}"
KEY_PASS="\${KEY_PASS:-$SCRIPT_KEY_ALIAS_PASSWORD}"
VALIDITY_DAYS="10000"
DNAME="CN=Usuario, OU=Dev, O=Empresa, L=Cidade, ST=Estado, C=BR"
mkdir -p "\$KEYSTORE_DIR"
if [ -f "\$KEYSTORE_FILE" ]; then
echo "⚠️ Keystore já existe: \$KEYSTORE_FILE"
exit 0
fi
echo "🔐 Gerando keystore release..."
keytool -genkeypair \
-deststoretype pkcs12 \
-keystore "\$KEYSTORE_FILE" \
-alias "\$ALIAS" \
-storepass "\$KEYSTORE_PASS" \
-keypass "\$KEY_PASS" \
-keyalg RSA \
-keysize 2048 \
-validity "\$VALIDITY_DAYS" \
-dname "\$DNAME" \
-v
echo "✅ Keystore criada: \$KEYSTORE_FILE"
EOF
chmod +x "$project_path/key.sh"
cat <<'EOF' >"$project_path/.classpath"
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry
kind="lib"
path="/home/ivan/Android/16/android-sdk-linux/platforms/android-16/android.jar"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
EOF
cat <<'EOF' >"$project_path/.project"
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyApp</name>
<comment>Projeto Android legado API 16 baseado em Ant</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
EOF
cat <<'EOF' >"$project_path/Makefile"
#===============================================================================
# Projeto Android legado - API 16 / Android 4.1
#===============================================================================
#-------------------------------------------------------------------------------
# Dispositivo
#-------------------------------------------------------------------------------
HOST := 192.168.2.101
PORT := 5555
DEVICE := $(HOST):$(PORT)
ADB_SELECTED_DEVICE := $(HOST):$(PORT)
#-------------------------------------------------------------------------------
# Caminhos principais
#-------------------------------------------------------------------------------
ANDROID_HOME := /home/ivan/Android/api/16/android-sdk-linux
JAVA_HOME := /home/ivan/.jenv/versions/1.8
LINUXBREW_HOME := /home/linuxbrew/.linuxbrew
ANDROID_TOOLS := $(ANDROID_HOME)/tools
ANDROID_PLATFORM_TOOLS := $(ANDROID_HOME)/platform-tools
#-------------------------------------------------------------------------------
# Ambiente exportado para Ant, adb e ferramentas Android antigas
#-------------------------------------------------------------------------------
export ANDROID_HOME
export JAVA_HOME
export ANDROID_SERIAL := $(DEVICE)
export PATH := $(JAVA_HOME)/bin:$(ANDROID_TOOLS):$(ANDROID_PLATFORM_TOOLS):$(PATH)
#-------------------------------------------------------------------------------
# Programas
#-------------------------------------------------------------------------------
ANT := JAVA_HOME=$(JAVA_HOME) PATH=$(JAVA_HOME)/bin:$(ANDROID_TOOLS):$(ANDROID_PLATFORM_TOOLS):$(PATH) /usr/bin/ant
JENV := $(LINUXBREW_HOME)/bin/jenv
XMLSTARLET := xmlstarlet
KEYTOOL := $(JAVA_HOME)/bin/keytool
ifdef ADB_SELECTED_DEVICE
ADB := $(ANDROID_PLATFORM_TOOLS)/adb -s $(ADB_SELECTED_DEVICE)
else
ADB := $(ANDROID_PLATFORM_TOOLS)/adb
endif
ADB_SHELL := $(ADB) shell
INPUT := $(ADB_SHELL) input
KEYEVENT := $(INPUT) keyevent
#-------------------------------------------------------------------------------
# Informações do projeto Android
#-------------------------------------------------------------------------------
PACKAGE := $(shell xmlstarlet select -T -t -v "//manifest/@package" -n AndroidManifest.xml)
MAINACTIVITY := $(PACKAGE).$(shell xmlstarlet select -T -t -v "//application/activity/@android:name" -n AndroidManifest.xml)
KEYSTORE_DIR = .keystore
KEYSTORE_FILE = $(KEYSTORE_DIR)/meu-release-key.keystore
ALIAS = minha-chave
KEYSTORE_PASS = senha123
KEY_PASS = senha123
VALIDITY_DAYS = 10000
DNAME = CN=Usuario, OU=Dev, O=Empresa, L=Cidade, ST=Estado, C=BR
# CORRIGIDO: Adicionado \ após o RSA
KEYTOOL_OPT = -genkeypair \
-deststoretype pkcs12 \
-keystore "$(KEYSTORE_FILE)" \
-alias "$(ALIAS)" \
-storepass "$(KEYSTORE_PASS)" \
-keypass "$(KEY_PASS)" \
-keyalg RSA \
-keysize 2048 \
-validity "$(VALIDITY_DAYS)" \
-dname "$(DNAME)" \
-v
.PHONY: status build debug release deploy install installr installd uninstall start clean key connect disconnect run stop fix-java-version
#-------------------------------------------------------------------------------
# Diagnóstico
#-------------------------------------------------------------------------------
status:
@echo "ANDROID_SERIAL=$(ANDROID_SERIAL)"
@echo "ANDROID_HOME=$(ANDROID_HOME)"
@echo "JAVA_HOME=$(JAVA_HOME)"
@echo "PACKAGE=$(PACKAGE)"
@echo "MAINACTIVITY=$(MAINACTIVITY)"
@java -version
@javac -version
@$(ANT) -diagnostics | grep -E "java.home|java.version|ant.java.version"
@$(ANT) -version
@$(JENV) version || true
@$(ADB) devices
#-------------------------------------------------------------------------------
# Configuração exigida pelo Ant antigo usando javac moderno
#-------------------------------------------------------------------------------
fix-java-version:
@echo key.store=$(KEYSTORE_FILE) > ant.properties
@echo key.alias=$(ALIAS) >> ant.properties
@echo key.store.password=$(KEYSTORE_PASS) >> ant.properties
@echo key.alias.password=$(KEY_PASS) >> ant.properties
@echo "java.source=1.8" >> ant.properties
@echo "java.target=1.8" >> ant.properties
#-------------------------------------------------------------------------------
# Dispositivo
#-------------------------------------------------------------------------------
connect:
@$(ADB) connect $(DEVICE)
disconnect:
@$(ADB) disconnect $(DEVICE)
#-------------------------------------------------------------------------------
# Build / deploy
#-------------------------------------------------------------------------------
build:
@$(ANT) debug
release: key
$(ANT) release
install: installd
installr:
$(ANT) installr
installd:
$(ANT) installd
uninstall:
@$(ADB) uninstall $(PACKAGE)
run:
@$(ADB) shell am start -n $(PACKAGE)/$(MAINACTIVITY)
stop:
@$(ADB) shell am force-stop $(PACKAGE)
deploy: uninstall build install run
clean:
@$(ANT) clean
rm -rf $(KEYSTORE_DIR)
key: fix-java-version
mkdir -p $(KEYSTORE_DIR)
@if [ -f "$(KEYSTORE_FILE)" ]; then \
echo "⚠️ Keystore já existe: $(KEYSTORE_FILE)"; \
else \
echo "🔐 Gerando keystore release..."; \
$(KEYTOOL) $(KEYTOOL_OPT); \
fi
#-------------------------------------------------------------------------------
# Ferramentas extras do projeto
#-------------------------------------------------------------------------------
include tools/tools.mk
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
.PHONY: list
list:
@LC_ALL=C $(MAKE) -pRrq -f $(firstword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$'
# IMPORTANT: The line above must be indented by (at least one)
# *actual TAB character* - *spaces* do *not* work.
EOF
mkdir -p "$project_path/tools"
cat <<'EOF' >"$project_path/tools/tools.mk"
.PHONY: \
screenshot \
screen.png \
shell \
show \
version \
home \
back \
menu \
ok \
assist \
devices \
notification \
profile-switch \
recents \
refresh \
search \
all-apps \
settings \
voice-assist
screenshot: ## Salva uma captura de tela
@echo "📸 Capturando tela..."
@$(ADB) exec-out screencap -p > screen.png 2>/dev/null || { \
$(ADB) shell screencap -p /sdcard/screen.png; \
$(ADB) pull /sdcard/screen.png screen.png >/dev/null; \
$(ADB) shell rm /sdcard/screen.png >/dev/null; \
}
@echo "✅ screen.png criada"
show: screen.png
eog screen.png
version:
@$(ADB) shell cat /proc/version
devices: ## lista dispositivos conectados via ADB
$(ADB) devices
shell: ## abre shell ADB
$(ADB) shell
# =============================================================================
# Navegação principal
# =============================================================================
back: ## envia botão voltar
$(KEYEVENT) KEYCODE_BACK
home: ## envia botão home
$(KEYEVENT) KEYCODE_HOME
menu: ## envia botão menu
$(KEYEVENT) KEYCODE_MENU
ok: ## envia botão OK (dpad center)
$(KEYEVENT) KEYCODE_DPAD_CENTER
recents: ## abre apps recentes
$(KEYEVENT) KEYCODE_APP_SWITCH
search: ## abre busca
$(KEYEVENT) KEYCODE_SEARCH
assist: ## abre assistente (API 19)
$(KEYEVENT) KEYCODE_ASSIST
voice-assist: ## assistente de voz (API 21)
$(KEYEVENT) KEYCODE_VOICE_ASSIST
all-apps: ## todos os apps (API 28)
$(KEYEVENT) KEYCODE_ALL_APPS
refresh: ## atualiza (API 28)
$(KEYEVENT) KEYCODE_REFRESH
# help: ## abre ajuda (API 23)
# $(KEYEVENT) KEYCODE_HELP
settings: ## abre configurações
$(KEYEVENT) KEYCODE_SETTINGS
notification: ## abre notificações
$(KEYEVENT) KEYCODE_NOTIFICATION
profile-switch: ## troca perfil (API 29)
$(KEYEVENT) KEYCODE_PROFILE_SWITCH
# =============================================================================
# Obtém o estado atual: 1 = tela apagada, 2 = tela acesa
# =============================================================================
define screen_state
$(shell $(ADB) shell dumpsys display | grep "mAllDisplayBlankStateFromPowerManager" | cut -d= -f2 )
endef
.PHONY: on-screen off-screen onoff-screen
# Liga a tela (se apagada)
on-screen:
@if [ "$(screen_state)" = "1" ]; then \
echo "Tela apagada -> ligando..."; \
$(ADB) shell input keyevent 26; \
else \
echo "Tela já está acesa."; \
fi
# Apaga a tela (se acesa)
off-screen:
@if [ "$(screen_state)" = "2" ]; then \
echo "Tela acesa -> apagando..."; \
$(ADB) shell input keyevent 26; \
else \
echo "Tela já está apagada."; \
fi
onoff-screen:
$(ADB) shell input keyevent KEYCODE_POWER
EOF
dialog --msgbox "✅ Projeto criado com suporte a release!
📁 Localização:
$project_path
🔨 Debug:
cd $project_path
make debug
🔐 Release assinado:
make release
📲 Deploy release:
make deploy" 17 68
dialog --yesno "📂 Abrir o diretório do projeto no gerenciador de arquivos?" 8 58
if [ $? -eq 0 ]; then
if command -v nautilus &>/dev/null; then
nautilus "$project_path" &
elif command -v dolphin &>/dev/null; then
dolphin "$project_path" &
elif command -v thunar &>/dev/null; then
thunar "$project_path" &
else
dialog --msgbox "⚠️ Nenhum gerenciador conhecido encontrado.
📁 Projeto em:
$project_path" 10 62
fi
fi
}
# Inicialização
check_dependencies
# Configurações padrão
target="$DEFAULT_TARGET"
project_name="$DEFAULT_NAME"
base_path="$DEFAULT_PATH"
activity_name="$DEFAULT_ACTIVITY"
package_name="$DEFAULT_PACKAGE"
dialog --msgbox "🤖 Criador de Projetos Android
📦 ANDROID_HOME:
$ANDROID_HOME
🧰 PATH SDK:
$(echo "$PATH" | grep -o "$ANDROID_HOME[^:]*" | head -1)
Pressione ENTER para continuar..." 13 74
main_menu
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment