Androidlanat / app.py
Akwbw's picture
Update app.py
07e4a8b verified
Raw
History Blame Contribute Delete
5.86 kB
import streamlit as st
import os, zipfile, subprocess, shutil
st.set_page_config(page_title="Android Build Server", layout="centered")
st.title("πŸ“± Android APK Generator")
st.markdown("Flutter ya Native Android β€” dono projects ka APK banayega aur **Auto-Sign** karega.")
def setup_java_env():
# Automatically detect valid JAVA_HOME path from system java binary
current_jh = os.environ.get("JAVA_HOME", "")
if not current_jh or not os.path.exists(os.path.join(current_jh, "bin", "java")):
java_bin = shutil.which("java")
if java_bin:
real_path = os.path.realpath(java_bin)
detected_jh = os.path.dirname(os.path.dirname(real_path))
os.environ["JAVA_HOME"] = detected_jh
def generate_keystore():
kp = "debug.keystore"
if not os.path.exists(kp):
subprocess.run([
"keytool","-genkey","-v","-keystore",kp,"-storepass","android",
"-alias","androiddebugkey","-keypass","android","-keyalg","RSA",
"-keysize","2048","-validity","10000",
"-dname","CN=AndroidDebug,O=Android,C=US"
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return kp
def find_apk(d):
for r,_,fs in os.walk(d):
for f in fs:
if f.endswith(".apk") and "release" in f.lower():
return os.path.join(r,f)
return None
def sign_apk(unsigned):
al = "aligned.apk"; sg = "Installable_App.apk"
try:
subprocess.run(["zipalign","-v","-p","4",unsigned,al],
stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL,check=True)
target = al
except:
target = unsigned
generate_keystore()
r = subprocess.run([
"apksigner","sign","--ks","debug.keystore","--ks-pass","pass:android",
"--out",sg,target
], capture_output=True, text=True)
return sg if r.returncode == 0 else None
f = st.file_uploader("Project ZIP Upload Karein", type=["zip"])
if f is not None:
if st.button("πŸ”¨ Create & Sign APK"):
setup_java_env() # Auto detect and set JAVA_HOME
sts = st.empty(); bar = st.progress(0)
if os.path.exists("project_extract"): shutil.rmtree("project_extract")
os.makedirs("project_extract")
sts.info("πŸ“¦ ZIP extract ho raha hai...")
with open("uploaded_project.zip","wb") as w: w.write(f.getbuffer())
with zipfile.ZipFile("uploaded_project.zip","r") as z: z.extractall("project_extract")
bar.progress(15)
flutter_root = None; native_root = None
for r,_,fs in os.walk("project_extract"):
if "pubspec.yaml" in fs and not flutter_root: flutter_root = r
if "gradlew" in fs and not native_root: native_root = r
unsigned = None
if flutter_root:
sts.info("🟦 Flutter project β€” flutter build apk chal raha hai...")
bar.progress(20)
android_dir = os.path.join(flutter_root, "android")
if not os.path.exists(android_dir):
os.makedirs(android_dir)
sdk_dir = os.environ.get('ANDROID_HOME', os.environ.get('ANDROID_SDK_ROOT', '/sdk'))
flutter_dir = os.environ.get('FLUTTER_HOME', '/opt/flutter')
with open(os.path.join(android_dir, "local.properties"), "w") as lf:
lf.write(f"sdk.dir={sdk_dir}\n")
lf.write(f"flutter.sdk={flutter_dir}\n")
lf.write("flutter.buildMode=release\n")
r1 = subprocess.run(["flutter","pub","get"], cwd=flutter_root, capture_output=True, text=True)
if r1.returncode != 0:
st.error("❌ flutter pub get fail!"); st.text(r1.stderr[-2000:])
else:
bar.progress(35)
r2 = subprocess.run(["flutter","build","apk","--release"], cwd=flutter_root, capture_output=True, text=True)
bar.progress(85)
if r2.returncode == 0:
apk_dir = os.path.join(flutter_root,"build","app","outputs","flutter-apk")
unsigned = find_apk(apk_dir)
else:
st.error("❌ Flutter Build Failed!")
st.text_area("Error Log", r2.stderr[-3000:], height=250)
elif native_root:
sts.info("🟩 Native Android project β€” gradlew assembleRelease chal raha hai...")
bar.progress(20)
sdk_dir = os.environ.get('ANDROID_HOME', os.environ.get('ANDROID_SDK_ROOT', '/sdk'))
with open(os.path.join(native_root, "local.properties"), "w") as lf:
lf.write(f"sdk.dir={sdk_dir}\n")
subprocess.run(["chmod","+x",os.path.join(native_root,"gradlew")])
bar.progress(25)
r = subprocess.run(["./gradlew","assembleRelease","--no-daemon","--stacktrace"],
cwd=native_root, capture_output=True, text=True)
bar.progress(85)
if r.returncode == 0:
unsigned = find_apk(native_root)
else:
st.error("❌ Gradle Build Failed!")
st.text_area("Error Log", r.stderr[-3000:], height=250)
else:
st.error("❌ ZIP mein na pubspec.yaml mila, na gradlew.")
if unsigned and os.path.exists(unsigned):
sts.info("πŸ” APK sign ho raha hai...")
sg = sign_apk(unsigned)
if sg:
bar.progress(100); sts.success("πŸŽ‰ APK Ready!")
with open(sg,"rb") as dl:
st.download_button("⬇️ Download APK", data=dl, file_name=sg, mime="application/vnd.android.package-archive")
else:
st.error("Signing fail ho gayi.")
if os.path.exists("uploaded_project.zip"): os.remove("uploaded_project.zip")