import os import subprocess from flask import Flask, request, render_template, send_from_directory, flash, redirect, url_for from werkzeug.utils import secure_filename app = Flask(__name__) app.secret_key = 'supersecretkey' UPLOAD_FOLDER = 'uploads' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER) @app.route('/') def index(): """Renders the main page with the URL input form.""" return render_template('index.html') @app.route('/build', methods=['POST']) def build_apk(): """Handles the form submission and initiates the APK build.""" url = request.form.get('url') if not url: flash('Please provide a URL.') return redirect(url_for('index')) # Sanitize the URL to create a valid project name project_name = secure_filename(url.replace('https://', '').replace('http://', '').replace('.', '_')) project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_name) if not os.path.exists(project_path): os.makedirs(project_path) # Create the main.py for the Android app main_py_content = f""" from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.lang import Builder from kivy.uix.webview import WebView Builder.load_string(''' : orientation: 'vertical' WebView: id: webview url: '{url}' ''') class WebViewLayout(BoxLayout): pass class SiteToApkApp(App): def build(self): return WebViewLayout() if __name__ == '__main__': SiteToApkApp().run() """ with open(os.path.join(project_path, 'main.py'), 'w') as f: f.write(main_py_content) # Create the requirements.txt for the Android app with open(os.path.join(project_path, 'requirements.txt'), 'w') as f: f.write('kivy\n') f.write('kivy-webview\n') # Initiate the build process using a separate script or a task queue # For simplicity, we'll call buildozer directly here. # In a real-world application, you would use a task queue like Celery. try: # Initialize buildozer subprocess.run(['buildozer', '-v', 'init'], cwd=project_path, check=True) # Update buildozer.spec for webview and permissions spec_path = os.path.join(project_path, 'buildozer.spec') with open(spec_path, 'r') as f: spec_content = f.read() spec_content = spec_content.replace( '# (list) Requirements to be installed (in order separated by commas)\nrequirements = python3,kivy', 'requirements = python3,kivy,kivy-webview' ) spec_content += '\nandroid.permissions = INTERNET' with open(spec_path, 'w') as f: f.write(spec_content) # Run the build subprocess.run(['buildozer', '-v', 'android', 'debug'], cwd=project_path, check=True) # Find the generated APK bin_dir = os.path.join(project_path, 'bin') apk_files = [f for f in os.listdir(bin_dir) if f.endswith('.apk')] if apk_files: return redirect(url_for('download_file', project_name=project_name, filename=apk_files[0])) else: flash('Build failed: APK not found.') return redirect(url_for('index')) except subprocess.CalledProcessError as e: flash(f'An error occurred during the build process: {e}') return redirect(url_for('index')) except FileNotFoundError: flash('Buildozer not found. Make sure it is installed and in your PATH.') return redirect(url_for('index')) @app.route('/uploads//') def download_file(project_name, filename): """Provides a download link for the generated APK.""" return send_from_directory(os.path.join(app.config['UPLOAD_FOLDER'], project_name, 'bin'), filename, as_attachment=True) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)