Spaces:
Sleeping
Sleeping
| 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") |