Primeiro
1. Alterando para o Tipo Makefile
- 1. Clique com o botão direito no seu projeto no Solution Explorer e selecione Propriedades.
- 2. No topo, certifique-se de selecionar Todas as Configurações (All Configurations)
- 3. Vá em Propriedades de Configuração > Geral.
- 4. Em Tipo de Configuração (Configuration Type), mude para Makefile. Clique em Aplicar.
2. Configurando as Linhas de Comando
Agora que o projeto é um Makefile, uma nova aba chamada NMake aparecerá nas propriedades. É ali que vamos mapear os botões do Visual Studio para o seu script PowerShell:
- 1. Vá em Propriedades de Configuração > NMake.
- 2. Configure os seguintes campos:
- Linha de Comando de Build (Build Command Line):
$(ProjectDir)_build.bat
- Linha de Comando de Rebuild (Rebuild All Command Line):
$(ProjectDir)_build.bat
- Linha de Comando de Limpeza (Clean Command Line):
cmd /c "del /q JogoNormal.apk 2>nul & rmdir /s /q lib app\com app\src\main\obj 2>nul"
- 3. Clique em Aplicar e Ok.
Segundo
1. Configurar os Caminhos de Inclusão no Visual Studio (IntelliSense)
Para o editor de texto do Visual Studio reconhecer as funções do OpenGL ES (como glClear, glGenBuffers) e tirar os sublinhados vermelhos de erro enquanto você programa:
- 1. No Visual Studio, clique com o botão direito no seu projeto no Solution Explorer e selecione Propriedades.
- 2. No menu lateral, expanda Propriedades de Configuração e clique em NMake.
- 3. No campo Caminhos de Inclusão (Include Search Path), copie e cole exatamente este endereço:
C:\Program Files (x86)\Android\AndroidNDK\android-ndk-r23c\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\include
- 4. Clique em Aplicar e depois em OK.
2. Criar as Pastas que o Script Exige
Se você tentar rodar o script agora, ele vai dar erro dizendo que não encontrou o manifesto ou os arquivos Java. Vamos criar essa estrutura básica vazia na pasta do seu projeto (horror-game) para o script ter o que compilar:
- 1. Abra a pasta do seu projeto no explorador de arquivos.
- 2. Crie uma pasta chamada app.
- 3. Dentro de app, crie a estrutura de pastas: com\exemplo\ (de modo que fique app\com\exemplo\).
- 4. Volte para a pasta app, crie a estrutura: src\main\ (de modo que fique app\src\main\).
Terceiro
1. Criar o Arquivo Java (MainActivity.java)
Este arquivo será a tela inicial do seu aplicativo. Como queremos apenas um APK normal para testar, ele vai apenas exibir uma tela padrão.
- 1. Vá até a pasta que você criou em seu projeto: app\com\exemplo\
- 2. Crie um arquivo de texto e mude o nome completo dele para MainActivity.java (certifique-se de que a extensão não ficou .java.txt).
- 3. Abra-o com o Bloco de Notas ou o próprio Visual Studio e cole o seguinte código:
package com.exemplo;
import android.app.Activity;
import android.os.Bundle;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MainActivity extends Activity {
private GLSurfaceView glView;
// 1. Carrega o arquivo "libmain.so" gerado pelo compilador C++ do NDK
static {
System.loadLibrary("main");
}
// 2. Declara as funções nativas implementadas no main.cpp
private native void nativoAoCriar();
private native void nativoMudarTela(int largura, int altura);
private native void nativoRenderizarQuadro();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 3. Inicializa a View do OpenGL e define a versão 3.0
glView = new GLSurfaceView(this);
glView.setEGLContextClientVersion(3);
// 4. Conecta os eventos de desenho do Android com o C++
glView.setRenderer(new GLSurfaceView.Renderer() {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
nativoAoCriar();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
nativoMudarTela(width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
nativoRenderizarQuadro();
}
});
setContentView(glView);
}
}
2. Criar o Manifesto do Android (AndroidManifest.xml)
O manifesto é o arquivo de configuração que diz ao sistema operacional Android qual classe deve ser executada quando o usuário clica no ícone do aplicativo.
- 1. Vá até a outra pasta que você criou: app\src\main\
- 2. Crie um arquivo de texto e mude o nome para AndroidManifest.xml
- 3. Abra o arquivo e cole a seguinte estrutura básica:
<?xml version="1.0" encoding="utf-8" ?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exemplo"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="26" android:targetSdkVersion="36" />
<application android:label="Meu App Basico"
android:allowBackup="true">
<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>
Quarto
1. Estruturação do Código Nativo C++ (main.cpp)
Este arquivo conterá o código C++ que recebe as instruções da MainActivity.java através do JNI e gerencia os comandos gráficos da GPU.
- 1. Na raiz do projeto, crie um arquivo de texto e mude o nome para main.cpp
- 2. Abra o arquivo e cole a seguinte estrutura base do OpenGL ES 3.0:
#include <jni.h>
#include <GLES3/gl3.h>
#include <android/log.h>
#define LOG_TAG "Jogo3D"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
extern "C" {
// Chamado uma vez quando a tela do OpenGL é criada
JNIEXPORT void JNICALL
Java_com_exemplo_MainActivity_nativoAoCriar(JNIEnv* env, jobject obj) {
LOGI("OpenGL ES 3.0 Inicializado pelo C++!");
// Define a cor de fundo inicial (Vermelho escuro/Bordô)
glClearColor(0.5f, 0.0f, 0.1f, 1.0f);
}
// Chamado sempre que a tela muda de tamanho (ex: rotacionar o celular)
JNIEXPORT void JNICALL
Java_com_exemplo_MainActivity_nativoMudarTela(JNIEnv* env, jobject obj, jint largura, jint altura) {
// Ajusta a área de desenho para o novo tamanho da tela
glViewport(0, 0, largura, altura);
}
// Chamado em loop constante para desenhar o jogo (Frame Rate)
JNIEXPORT void JNICALL
Java_com_exemplo_MainActivity_nativoRenderizarQuadro(JNIEnv* env, jobject obj) {
// Limpa a tela aplicando a cor definida no glClearColor
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
Quinto
1. Criacao da Chave de Assinatura (.keystore)
Este passo detalha como gerar o arquivo de chave digital necessario para assinar o aplicativo (.apk), permitindo que o Android aceite a instalacao dele.
- Abra o Prompt de Comando (cmd) do Windows.
- Navegue ate a pasta raiz do seu projeto utilizando o comando de navegacao cd.
- Execute a ferramenta keytool do Java utilizando os parametros de senha do seu script de build.
cd /d "C:\Users\USER_NAME\source\repos\android\program-zero\default-android-program"
"C:\Program Files\Java\jdk-27\bin\keytool.exe" -genkeypair -v -keystore minha-chave.keystore -alias minha-chave -keyalg RSA -keysize 2048 -validity 10000 -storepass 123456 -keypass 123456 -dname "CN=Exemplo, OU=Desenvolvimento, O=Jogo, L=Cidade, S=Estado, C=BR"
Nota: O comando criara o arquivo "minha-chave.keystore" diretamente na raiz da pasta. Esse arquivo deve permanecer ao lado do seu script "_build.bat".
Sexto
1. Criacao do Arquivo de Automacao de Build (_build.bat)
Este passo detalha como criar o arquivo de lote (.bat) responsavel por automatizar o processo de compilacao do codigo C++ e Java, empacotamento dos recursos, alinhamento e assinatura do APK final.
- Na raiz do seu projeto, crie um arquivo de texto e mude o nome completo para _build.bat (certifique-se de remover a extensao .txt).
- Clique com o botão direito no arquivo e selecione Editar (ou abra com o Bloco de Notas).
- Cole o codigo abaixo, salve e feche o arquivo. Para rodar o build, basta dar dois cliques no arquivo.
@echo off
:: ==============================================================================
:: PASSO 1: CONFIGURACAO DE AMBIENTE E CAMINHOS
:: ==============================================================================
cd /d "%~dp0"
if not exist "lib\arm64-v8a" mkdir "lib\arm64-v8a"
:: ==============================================================================
:: PASSO 2: COMPILACAO C++ (EMBUTINDO A LIBC++ DE FORMA ESTATICA)
:: ==============================================================================
echo [1/5] Compilando codigo nativo C++ (Estatico)...
"C:\Program Files (x86)\Android\AndroidNDK\android-ndk-r23c\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe" ^
--target=aarch64-linux-android26 ^
--sysroot="C:\Program Files (x86)\Android\AndroidNDK\android-ndk-r23c\toolchains\llvm\prebuilt\windows-x86_64\sysroot" ^
-fPIC -shared -static-libstdc++ -o "lib\arm64-v8a\libmain.so" "main.cpp" ^
-lGLESv3 -lGLESv2 -lEGL -llog -landroid
if %errorlevel% neq 0 goto erro
:: ==============================================================================
:: PASSO 3: COMPILACAO JAVA (.JAVA -> .CLASS)
:: ==============================================================================
echo [2/5] Compilando arquivos Java...
"C:\Program Files\Java\jdk-27\bin\javac.exe" ^
--release 8 ^
-cp "C:\Program Files (x86)\Android\android-sdk\platforms\android-36\android.jar" ^
-d "app" "app\com\exemplo\MainActivity.java"
if %errorlevel% neq 0 goto erro
:: ==============================================================================
:: PASSO 4: PROCESSAMENTO DE CODIGO (.CLASS -> CLASSES.DEX)
:: ==============================================================================
echo [3/5] Transformando bytecode Java em Dex...
call "C:\Program Files (x86)\Android\android-sdk\build-tools\36.0.0\d8.bat" ^
--output app\classes.zip "app\com\exemplo\MainActivity.class" ^
--lib "C:\Program Files (x86)\Android\android-sdk\platforms\android-36\android.jar"
tar -xf "app\classes.zip" -C "app"
del /q "app\classes.zip"
:: ==============================================================================
:: PASSO 5: COMPILACAO DE RECURSOS (AAPT2)
:: ==============================================================================
echo [4/5] Compilando o AndroidManifest com AAPT2...
"C:\Program Files (x86)\Android\android-sdk\build-tools\36.0.0\aapt2.exe" ^
link -o "recursos_novo.apk" ^
--manifest "app\src\main\AndroidManifest.xml" ^
-I "C:\Program Files (x86)\Android\android-sdk\platforms\android-36\android.jar"
if %errorlevel% neq 0 goto erro
:: ==============================================================================
:: PASSO 6: EMPACOTAMENTO, ALINHAMENTO E ASSINATURA
:: ==============================================================================
echo [5/5] Montando e assinando o APK final...
copy /y "app\classes.dex" "." >nul
"C:\Program Files\Java\jdk-27\bin\jar.exe" uf recursos_novo.apk classes.dex
"C:\Program Files\Java\jdk-27\bin\jar.exe" uf recursos_novo.apk lib
"C:\Program Files (x86)\Android\android-sdk\build-tools\36.0.0\zipalign.exe" -v -f 4 "recursos_novo.apk" "jogo-alinhado.apk" >nul
"C:\Program Files\Java\jdk-27\bin\java.exe" -jar "C:\Program Files (x86)\Android\android-sdk\build-tools\36.0.0\lib\apksigner.jar" ^
sign --ks "minha-chave.keystore" --ks-pass pass:123456 --out "JogoNormal.apk" "jogo-alinhado.apk"
del /q "jogo-alinhado.apk" 2>nul
del /q "recursos_novo.apk" 2>nul
del /q "classes.dex" 2>nul
echo.
echo ==============================================================================
echo APK gerado com sucesso em: %~dp0JogoNormal.apk
echo ==============================================================================
pause
exit /b 0
:erro
echo Ocorreu um erro em alguma das etapas do Build. Verifique as mensagens acima.
pause
exit /b 1