Spaces:
Build error
Build error
| import os, zipfile, subprocess, shutil, uuid, requests, traceback | |
| from flask import Flask, request, jsonify, send_file | |
| from flask_cors import CORS | |
| app = Flask(__name__) | |
| # Enable CORS for external HTML Requests! | |
| CORS(app) | |
| def generate_keystore(work_dir): | |
| keystore_path = os.path.abspath(os.path.join(work_dir, "debug.keystore")) | |
| cmd = [ | |
| "keytool", "-genkey", "-v", "-keystore", keystore_path, | |
| "-storepass", "android", "-alias", "androiddebugkey", "-keypass", "android", | |
| "-keyalg", "RSA", "-keysize", "2048", "-validity", "10000", | |
| "-dname", "CN=AndroidDebug,O=Android,C=US" | |
| ] | |
| subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
| return keystore_path | |
| def push_to_appetize(apk_path, api_token): | |
| """ Upload to appetize platform to stream App inside the web lightweight layer """ | |
| url = "https://api.appetize.io/v1/apps" | |
| try: | |
| with open(apk_path, "rb") as app_file: | |
| files = {"file": app_file} | |
| headers = {"Authorization": f"Bearer {api_token}"} | |
| # Data stream params config | |
| data = { "platform": "android" } | |
| resp = requests.post(url, headers=headers, files=files, data=data) | |
| if resp.status_code == 200: | |
| json_data = resp.json() | |
| public_key = json_data.get("publicKey", "") | |
| return f"https://appetize.io/embed/{public_key}?device=pixel7&scale=80&autoplay=true&language=en" | |
| else: | |
| return f"API_REJECTED: Status Code {resp.status_code}. Response: {resp.text}" | |
| except Exception as e: | |
| return f"REQUEST_FAILED: {str(e)}" | |
| def index(): | |
| try: | |
| return send_file('index.html') | |
| except Exception as e: | |
| return f"Index File load failed: {str(e)}", 500 | |
| def build_and_preview_app(): | |
| # Hugging Face Settings/Secrets Fetcher API variable | |
| APPETIZE_API_KEY = os.getenv("APPETIZE_API_KEY", "").strip() | |
| if not APPETIZE_API_KEY: | |
| return jsonify({'success': False, 'message': 'System Config Error: Hugging Face space variables missing (APPETIZE_API_KEY). Go to space settings and add it!'}) | |
| if 'file' not in request.files: | |
| return jsonify({'success': False, 'message': 'No zip file sent with request!'}) | |
| file = request.files['file'] | |
| run_id = str(uuid.uuid4())[:8] | |
| work_dir = os.path.abspath(f"build_{run_id}") | |
| os.makedirs(work_dir, exist_ok=True) | |
| zip_location = os.path.join(work_dir, "android_code.zip") | |
| extract_path = os.path.join(work_dir, "src") | |
| try: | |
| file.save(zip_location) | |
| with zipfile.ZipFile(zip_location, "r") as zip_ref: | |
| zip_ref.extractall(extract_path) | |
| project_folder = next((root for root, _, files in os.walk(extract_path) if "gradlew" in files), None) | |
| if not project_folder: | |
| return jsonify({'success': False, 'message': 'Missing build code folder, (gradlew format mismatch). Check Zip Content!'}) | |
| subprocess.run(["chmod", "+x", "gradlew"], cwd=project_folder) | |
| result = subprocess.run(["./gradlew", "assembleRelease", "--no-daemon", "--stacktrace"], | |
| cwd=project_folder, capture_output=True, text=True) | |
| if result.returncode == 0: | |
| final_unsigned_apk = next((os.path.join(root, fi) | |
| for root, _, files in os.walk(project_folder) | |
| for fi in files if fi.endswith(".apk") and "release" in fi), None) | |
| if final_unsigned_apk: | |
| ks = generate_keystore(work_dir) | |
| apk_done = os.path.join(work_dir, f"Final_App_{run_id}.apk") | |
| subprocess.run(["apksigner", "sign", "--ks", ks, "--ks-pass", "pass:android", "--out", apk_done, final_unsigned_apk]) | |
| # Request Live url Engine Logic! | |
| api_response_url = push_to_appetize(apk_done, APPETIZE_API_KEY) | |
| if api_response_url.startswith("http"): | |
| return jsonify({'success': True, 'preview_url': api_response_url}) | |
| else: | |
| return jsonify({'success': False, 'message': f'Server processed well but Live App Connection failed. Message details from Appetaize: {api_response_url}'}) | |
| else: | |
| return jsonify({'success': False, 'message': 'Folder execution built success! However system fails identifying output extension \'.apk\''}) | |
| return jsonify({'success': False, 'message': f"Syntax source script syntax/library compile Gradle break:\n\n{result.stderr[-500:]}"}) | |
| except Exception as e: | |
| # Here Python completely grabs crashes making no screen turns 500 html format errors rather it sends precise data logs inside Response!! | |
| stacktrace_issue = traceback.format_exc() | |
| print("INTERNAL BUG EXPOSED:\n" + stacktrace_issue) | |
| return jsonify({'success': False, 'message': f"Server Backend Fatal Alert: {str(e)} \nView Server Logs."}) | |
| finally: | |
| # House Keeping Data | |
| if os.path.exists(work_dir): | |
| try: shutil.rmtree(work_dir) | |
| except: pass | |
| if __name__ == '__main__': | |
| # Launch system port standard map rule ! | |
| app.run(host='0.0.0.0', port=7860) |