File size: 5,894 Bytes
da5c160
 
 
 
 
 
 
 
 
e6abcb7
 
da5c160
e6abcb7
adca9d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da5c160
 
 
adca9d6
da5c160
 
 
adca9d6
da5c160
 
 
 
adca9d6
da5c160
 
 
 
 
 
 
adca9d6
da5c160
 
 
 
 
 
 
6f0db2a
da5c160
adca9d6
 
da5c160
 
 
e6abcb7
adca9d6
e6abcb7
adca9d6
da5c160
 
 
adca9d6
da5c160
 
 
 
 
 
adca9d6
da5c160
 
e6abcb7
da5c160
adca9d6
 
6f0db2a
da5c160
adca9d6
 
 
da5c160
adca9d6
e6abcb7
adca9d6
e6abcb7
 
6f0db2a
e6abcb7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
adca9d6
e6abcb7
 
 
 
 
 
 
adca9d6
e6abcb7
 
adca9d6
e6abcb7
adca9d6
da5c160
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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")