package com.phenomrom.healerman; import android.content.res.AssetManager; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import com.getcapacitor.Bridge; import org.json.JSONObject; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.zip.GZIPInputStream; /** Streams shared APK objects at their original logical URLs; no expanded disk copy. */ final class BundledContentAssets { private final Bridge bridge; private final AssetManager assets; private JSONObject files; BundledContentAssets(Bridge bridge) { this.bridge = bridge; this.assets = bridge.getContext().getAssets(); } private synchronized JSONObject files() throws Exception { if (files == null) { try (InputStream input = assets.open("public/content/bootstrap-manifest.json")) { ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buffer = new byte[16384]; int count; while ((count = input.read(buffer)) != -1) output.write(buffer, 0, count); files = new JSONObject(output.toString("UTF-8")).getJSONObject("files"); } } return files; } WebResourceResponse intercept(WebResourceRequest request) { if (!"GET".equals(request.getMethod()) || !bridge.getHost().equals(request.getUrl().getAuthority()) || !bridge.getScheme().equals(request.getUrl().getScheme())) return null; String path = request.getUrl().getPath(); if (path == null || !(path.startsWith("/assets/") || path.startsWith("/basis/") || path.startsWith("/data/"))) return null; try { JSONObject entry = files().optJSONObject(path); if (entry == null) return null; JSONObject download = entry.optJSONObject("download"); String objectUrl = (download == null ? entry : download).getString("url"); if (!objectUrl.matches("/content/bundled/[a-f0-9]{64}\\.[a-z0-9]+(?:\\.g(?:z|zip))?")) return null; InputStream input = assets.open("public" + objectUrl); if (download != null) { try { input = new GZIPInputStream(input, 128 * 1024); } catch (Exception error) { input.close(); throw error; } } Map headers = new HashMap<>(); headers.put("Content-Length", String.valueOf(entry.getLong("bytes"))); headers.put("Cache-Control", "public, max-age=3600"); return new WebResourceResponse(mimeType(path), null, 200, "OK", headers, input); } catch (Exception error) { return new WebResourceResponse("text/plain", "UTF-8", 500, "Bundled asset unavailable", new HashMap<>(), new ByteArrayInputStream("Bundled asset unavailable.".getBytes(StandardCharsets.UTF_8))); } } private static String mimeType(String path) { String extension = path.substring(path.lastIndexOf('.') + 1); switch (extension) { case "glb": return "model/gltf-binary"; case "json": return "application/json"; case "js": return "text/javascript"; case "wasm": return "application/wasm"; case "ktx2": return "image/ktx2"; case "png": return "image/png"; case "webp": return "image/webp"; case "avif": return "image/avif"; case "svg": return "image/svg+xml"; case "mp3": return "audio/mpeg"; case "ogg": return "audio/ogg"; case "wav": return "audio/wav"; case "webm": return "video/webm"; default: return "application/octet-stream"; } } }