feat: initial commit - Carinha Control Panel v1.0 com UI glassmorphism, watch-bar, emojis, braco robotico e conversa IA
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
"""Build Windows/Linux usando JDK e Android SDK existentes; sem Gradle."""
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
DEFAULT_TOOLS = os.environ.get('CARINHA_TOOLS', 'C:/Users/JullioPC/Documents/Open/orange-pi-zero3/android/tools')
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--tools', default=DEFAULT_TOOLS)
|
||||
args = parser.parse_args()
|
||||
tools = Path(args.tools)
|
||||
suffix = '.exe' if os.name == 'nt' else ''
|
||||
java = tools / 'jdk/bin' / ('java' + suffix)
|
||||
javac = tools / 'jdk/bin' / ('javac' + suffix)
|
||||
bt = tools / 'android-sdk/build-tools/34.0.0'
|
||||
android = tools / 'android-sdk/platforms/android-34/android.jar'
|
||||
for path in (java, javac, android, bt / ('aapt2' + suffix), HERE / 'keystore.jks'):
|
||||
if not path.exists():
|
||||
raise SystemExit('Arquivo necessário não encontrado: ' + str(path))
|
||||
work = HERE.parents[2] / 'work'
|
||||
work.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def run(*command):
|
||||
subprocess.run([str(x) for x in command], check=True)
|
||||
|
||||
for name in ('carinha.html', 'camera.html'):
|
||||
shutil.copy2(HERE.parent / name, HERE / 'app/assets' / name)
|
||||
with tempfile.TemporaryDirectory(prefix='carinha-build-', dir=work) as folder:
|
||||
tmp = Path(folder)
|
||||
for name in ('compiled', 'classes', 'gen'):
|
||||
(tmp / name).mkdir()
|
||||
print('Recursos e manifesto', flush=True)
|
||||
run(bt / ('aapt2' + suffix), 'compile', '--dir', HERE / 'app/res', '-o', tmp / 'compiled/res.zip')
|
||||
run(bt / ('aapt2' + suffix), 'link', '-o', tmp / 'base.apk', '-I', android,
|
||||
'--manifest', HERE / 'app/AndroidManifest.xml', '-A', HERE / 'app/assets',
|
||||
'--java', tmp / 'gen', '--min-sdk-version', '21', '--target-sdk-version', '34', tmp / 'compiled/res.zip')
|
||||
sources = list((HERE / 'app/java').rglob('*.java')) + list((tmp / 'gen').rglob('*.java'))
|
||||
print('Java e DEX', flush=True)
|
||||
run(javac, '--release', '8', '-nowarn', '-classpath', android, '-d', tmp / 'classes', *sources)
|
||||
classes = list((tmp / 'classes').rglob('*.class'))
|
||||
run(java, '-cp', bt / 'lib/d8.jar', 'com.android.tools.r8.D8', '--lib', android,
|
||||
'--min-api', '21', '--output', tmp, *classes)
|
||||
with zipfile.ZipFile(tmp / 'base.apk', 'a', zipfile.ZIP_DEFLATED) as z:
|
||||
z.write(tmp / 'classes.dex', 'classes.dex')
|
||||
for native in (HERE / 'app/native/arm64-v8a').glob('*.so'):
|
||||
z.write(native, 'lib/arm64-v8a/' + native.name)
|
||||
run(bt / ('zipalign' + suffix), '-f', '-p', '4', tmp / 'base.apk', tmp / 'aligned.apk')
|
||||
print('Assinatura persistente', flush=True)
|
||||
run(java, '-jar', bt / 'lib/apksigner.jar', 'sign', '--ks', HERE / 'keystore.jks',
|
||||
'--ks-pass', 'pass:android', '--key-pass', 'pass:android', '--ks-key-alias', 'carinha',
|
||||
'--out', HERE / 'carinha-rosto.apk', tmp / 'aligned.apk')
|
||||
run(java, '-jar', bt / 'lib/apksigner.jar', 'verify', HERE / 'carinha-rosto.apk')
|
||||
with zipfile.ZipFile(HERE / 'carinha-rosto.apk') as z:
|
||||
required = {'AndroidManifest.xml', 'classes.dex', 'resources.arsc', 'assets/carinha.html', 'assets/camera.html', 'assets/transmissao.html', 'assets/qualidade-auto.js'}
|
||||
assert required.issubset(z.namelist()), 'APK incompleto'
|
||||
print('APK pronto: ' + str(HERE / 'carinha-rosto.apk'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user