import streamlit as st import os import zipfile import subprocess import shutil # Page Config st.set_page_config(page_title="Android Build Server", layout="centered") st.title("📱 Android APK Generator (Final Production)") st.markdown("Zip upload karein. Server APK banayega aur **Auto-Sign** karega.") # --- HELPER: GENERATE KEY --- def generate_keystore(): keystore_path = "debug.keystore" if not os.path.exists(keystore_path): 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 uploaded_file = st.file_uploader("Project ZIP File Upload Karein", type=["zip"]) if uploaded_file is not None: if st.button("🔨 Create & Sign APK"): status_text = st.empty() progress_bar = st.progress(0) # 1. Cleanup if os.path.exists("project_extract"): shutil.rmtree("project_extract") os.makedirs("project_extract", exist_ok=True) # 2. Extract status_text.info("Extracting ZIP file...") with open("uploaded_project.zip", "wb") as f: f.write(uploaded_file.getbuffer()) with zipfile.ZipFile("uploaded_project.zip", "r") as zip_ref: zip_ref.extractall("project_extract") progress_bar.progress(20) # 3. Find Root project_root = None for root, dirs, files in os.walk("project_extract"): if "gradlew" in files: project_root = root break if not project_root: st.error("❌ ZIP file mein 'gradlew' nahi mila.") else: # 4. Permissions status_text.info("Setting up Gradle...") gradlew_path = os.path.join(project_root, "gradlew") subprocess.run(["chmod", "+x", gradlew_path]) # 5. Build status_text.info("Building APK... (Wait karein)") # Hum assembleRelease chala rahe hain build_cmd = ["./gradlew", "assembleRelease", "--no-daemon", "--stacktrace"] try: result = subprocess.run( build_cmd, cwd=project_root, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) progress_bar.progress(60) if result.returncode == 0: status_text.info("✅ Build Successful! Signing APK...") # 6. Find Unsigned APK unsigned_apk = None for root, dirs, files in os.walk(project_root): for file in files: if file.endswith(".apk") and "release" in file: unsigned_apk = os.path.join(root, file) break if unsigned_apk: # 7. SIGNING (Direct System Commands) keystore = generate_keystore() signed_apk_name = "Installable_App.apk" aligned_apk = "aligned.apk" # Step A: ZipAlign (Important for installation) try: subprocess.run(["zipalign", "-v", "-p", "4", unsigned_apk, aligned_apk], stdout=subprocess.DEVNULL, check=True) apk_to_sign = aligned_apk except: # Agar align fail ho, to original use kar lo apk_to_sign = unsigned_apk # Step B: APKSigner sign_cmd = [ "apksigner", "sign", "--ks", keystore, "--ks-pass", "pass:android", "--out", signed_apk_name, apk_to_sign ] sign_result = subprocess.run(sign_cmd, capture_output=True, text=True) if sign_result.returncode == 0: status_text.success("🎉 APK Signed & Ready to Install!") progress_bar.progress(100) with open(signed_apk_name, "rb") as f: st.download_button( label="⬇️ Download Installable APK", data=f, file_name=signed_apk_name, mime="application/vnd.android.package-archive" ) else: st.error("Build hui magar Signing fail hogayi.") st.text_area("Signing Log", sign_result.stderr) else: st.error("APK file generate nahi hui.") else: st.error("❌ Build Failed!") st.text_area("Error Log", result.stderr, height=300) except Exception as e: st.error(f"System Error: {str(e)}") if os.path.exists("uploaded_project.zip"): os.remove("uploaded_project.zip")