File size: 4,756 Bytes
f350149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
import os, zipfile, subprocess, shutil, uuid, requests

app = Flask(__name__)
# Enable CORS for external HTML Requests calling this build system !
CORS(app)

# NOTE: Get this Free from appetize.io/docs
APPETIZE_API_KEY = "tok_hu46b6i3qxcxijamjmczaqdbv4" 

def generate_keystore(work_dir):
    keystore_path = os.path.join(work_dir, "debug.keystore")
    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

def push_to_appetize(apk_path):
    """ Upload to appetize platform to stream App inside the web lightweight layer """
    url = "https://api.appetize.io/v1/apps"
    with open(apk_path, "rb") as app_file:
        files = {"file": app_file}
        headers = {"Authorization": f"Bearer {APPETIZE_API_KEY}"}
        # Data stream params config
        data = { "platform": "android" } 
        resp = requests.post(url, headers=headers, files=files, data=data)
        
    if resp.status_code == 200:
        json_data = resp.json()
        public_key = json_data.get("publicKey", "")
        # Returns Web UI Iframe Player configured natively (Bijli ki trha speed aur Exact App replica)
        stream_link = f"https://appetize.io/embed/{public_key}?device=pixel7&scale=80&autoplay=true&language=en"
        return stream_link
    else:
        return None

@app.route('/', methods=['GET'])
def index():
    # Calling Custom HTML Design
    return send_file('index.html')

@app.route('/upload_project', methods=['POST'])
def build_and_preview_app():
    if 'file' not in request.files: 
        return jsonify({'success': False, 'message': 'Project Zip Error!'}), 400
    
    file = request.files['file']
    run_id = str(uuid.uuid4())[:8]
    work_dir = f"/app/build_{run_id}"
    os.makedirs(work_dir, exist_ok=True)
    
    zip_location = os.path.join(work_dir, "android_code.zip")
    extract_path = os.path.join(work_dir, "src")
    file.save(zip_location)

    try:
        with zipfile.ZipFile(zip_location, "r") as zip_ref:
            zip_ref.extractall(extract_path)
        
        project_folder = next((r for r, _, f in os.walk(extract_path) if "gradlew" in f), None)
        
        if not project_folder: 
            return jsonify({'success': False, 'message': 'Invalid Android source, missing gradlew'}), 400

        # Execute build permission sets and Start Lightning Compile Build
        subprocess.run(["chmod", "+x", "gradlew"], cwd=project_folder)
        result = subprocess.run(["./gradlew", "assembleRelease", "--no-daemon", "--stacktrace"], 
                               cwd=project_folder, capture_output=True, text=True)
        
        if result.returncode == 0:
            final_unsigned_apk = next((os.path.join(path, fi) 
                                       for path, _, fsi in os.walk(project_folder) 
                                       for fi in fsi if fi.endswith(".apk") and "release" in fi), None)
            
            if final_unsigned_apk:
                ks = generate_keystore(work_dir)
                apk_done = os.path.abspath(os.path.join(work_dir, f"Final_App_{run_id}.apk"))
                # Signing to enable live android deploy logic!
                subprocess.run(["apksigner", "sign", "--ks", ks, "--ks-pass", "pass:android", "--out", apk_done, final_unsigned_apk])
                
                # Cloud Live Stream Step
                iframe_url = push_to_appetize(apk_done)
                if iframe_url:
                    return jsonify({'success': True, 'preview_url': iframe_url})
                else:
                    return jsonify({'success': False, 'message': 'Compilation worked but Emulator Connection Failed. (Check APPETIZE Token)'})
            else:
                 return jsonify({'success': False, 'message': 'Gradle process built 0 Apps inside folders!'})
        
        return jsonify({'success': False, 'message': f"Compile failure on server! Msg:\n{result.stderr[-400:]}"})

    except Exception as e:
        return jsonify({'success': False, 'message': f"An issue raised handling system code. {str(e)}"})
    finally:
        # Save container limits from exceeding memory & size caps free hugs limit!
        try:
             shutil.rmtree(work_dir)
        except: pass

if __name__ == '__main__':
    # Listen actively within docker Hugging limits Space 7860 mapping setup limits !
    app.run(host='0.0.0.0', port=7860)