Akwbw commited on
Commit
068c3e6
·
verified ·
1 Parent(s): 3488bd2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +161 -0
app.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, send_file, Response
2
+ import os
3
+ import zipfile
4
+ import subprocess
5
+ import shutil
6
+
7
+ app = Flask(__name__)
8
+
9
+ # --- HELPER: GENERATE KEY (Same as before) ---
10
+ def generate_keystore():
11
+ keystore_path = "debug.keystore"
12
+ if not os.path.exists(keystore_path):
13
+ cmd = [
14
+ "keytool", "-genkey", "-v",
15
+ "-keystore", keystore_path,
16
+ "-storepass", "android",
17
+ "-alias", "androiddebugkey",
18
+ "-keypass", "android",
19
+ "-keyalg", "RSA",
20
+ "-keysize", "2048",
21
+ "-validity", "10000",
22
+ "-dname", "CN=AndroidDebug,O=Android,C=US"
23
+ ]
24
+ subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
25
+ return keystore_path
26
+
27
+ # --- ROUTE: HOME (HTML FORM FOR TESTING) ---
28
+ @app.route('/')
29
+ def index():
30
+ return '''
31
+ <!doctype html>
32
+ <title>Android Build Server</title>
33
+ <h1>Upload Project ZIP</h1>
34
+ <form action="/upload" method="post" enctype="multipart/form-data">
35
+ <input type="file" name="file" required>
36
+ <input type="submit" value="Build & Sign APK">
37
+ </form>
38
+ '''
39
+
40
+ # --- ROUTE: API ENDPOINT ---
41
+ @app.route('/upload', methods=['POST'])
42
+ def upload_file():
43
+ if 'file' not in request.files:
44
+ return "No file part", 400
45
+
46
+ file = request.files['file']
47
+ if file.filename == '':
48
+ return "No selected file", 400
49
+
50
+ if file:
51
+ # 1. Cleanup & Save
52
+ if os.path.exists("project_extract"):
53
+ shutil.rmtree("project_extract")
54
+ os.makedirs("project_extract", exist_ok=True)
55
+
56
+ zip_path = "uploaded_project.zip"
57
+ file.save(zip_path)
58
+
59
+ # 2. Extract
60
+ try:
61
+ with zipfile.ZipFile(zip_path, "r") as zip_ref:
62
+ zip_ref.extractall("project_extract")
63
+ except Exception as e:
64
+ return f"Error extracting ZIP: {str(e)}", 400
65
+
66
+ # 3. Find Root
67
+ project_root = None
68
+ for root, dirs, files in os.walk("project_extract"):
69
+ if "gradlew" in files:
70
+ project_root = root
71
+ break
72
+
73
+ if not project_root:
74
+ return "Error: ZIP file mein 'gradlew' nahi mila.", 400
75
+
76
+ # 4. Permissions
77
+ gradlew_path = os.path.join(project_root, "gradlew")
78
+ subprocess.run(["chmod", "+x", gradlew_path])
79
+
80
+ # 5. Build
81
+ # Hum assembleRelease chala rahe hain
82
+ build_cmd = ["./gradlew", "assembleRelease", "--no-daemon", "--stacktrace"]
83
+
84
+ try:
85
+ result = subprocess.run(
86
+ build_cmd,
87
+ cwd=project_root,
88
+ stdout=subprocess.PIPE,
89
+ stderr=subprocess.PIPE,
90
+ text=True
91
+ )
92
+
93
+ if result.returncode == 0:
94
+ # 6. Find Unsigned APK
95
+ unsigned_apk = None
96
+ for root, dirs, files in os.walk(project_root):
97
+ for f in files:
98
+ if f.endswith(".apk") and "release" in f:
99
+ unsigned_apk = os.path.join(root, f)
100
+ break
101
+
102
+ if unsigned_apk:
103
+ # 7. SIGNING
104
+ keystore = generate_keystore()
105
+ signed_apk_name = "Installable_App.apk"
106
+ aligned_apk = "aligned.apk"
107
+
108
+ # Full path for output
109
+ output_apk_path = os.path.abspath(signed_apk_name)
110
+
111
+ # Step A: ZipAlign
112
+ try:
113
+ subprocess.run(["zipalign", "-v", "-p", "4", unsigned_apk, aligned_apk],
114
+ stdout=subprocess.DEVNULL, check=True)
115
+ apk_to_sign = aligned_apk
116
+ except:
117
+ apk_to_sign = unsigned_apk
118
+
119
+ # Step B: APKSigner
120
+ sign_cmd = [
121
+ "apksigner", "sign",
122
+ "--ks", keystore,
123
+ "--ks-pass", "pass:android",
124
+ "--out", output_apk_path,
125
+ apk_to_sign
126
+ ]
127
+
128
+ sign_result = subprocess.run(sign_cmd, capture_output=True, text=True)
129
+
130
+ if sign_result.returncode == 0:
131
+ # CLEANUP ZIP before sending
132
+ if os.path.exists(zip_path):
133
+ os.remove(zip_path)
134
+
135
+ # RETURN THE SIGNED APK
136
+ return send_file(
137
+ output_apk_path,
138
+ as_attachment=True,
139
+ download_name=signed_apk_name,
140
+ mimetype="application/vnd.android.package-archive"
141
+ )
142
+ else:
143
+ # Signing Failed - Show Logs
144
+ logs = sign_result.stderr.splitlines()[:200]
145
+ return Response("\n".join(logs), status=500, mimetype="text/plain")
146
+ else:
147
+ return "Build Success but APK file not found.", 500
148
+ else:
149
+ # BUILD FAILED - RETURN FIRST 200 LINES OF LOGS
150
+ # Combining stdout and stderr to capture full context
151
+ full_log = result.stdout + "\n" + result.stderr
152
+ logs = full_log.splitlines()[:200]
153
+ error_message = "BUILD FAILED. LOGS (First 200 lines):\n\n" + "\n".join(logs)
154
+ return Response(error_message, status=500, mimetype="text/plain")
155
+
156
+ except Exception as e:
157
+ return f"System Error: {str(e)}", 500
158
+
159
+ if __name__ == '__main__':
160
+ # Hugging Face Spaces port 7860 use karta hai
161
+ app.run(host='0.0.0.0', port=7860)