From 7ac0116183bc63f7b1dde572a2d9fd654e79fd65 Mon Sep 17 00:00:00 2001 From: jslok Date: Tue, 21 Apr 2026 21:04:13 -0700 Subject: [PATCH] fix(android): load bundled res/raw assets in release builds In release builds, RN's AssetSourceResolver returns a bare Android resource identifier for non-drawable bundled assets (e.g. "myapp_assets_model_tflite"). java.net.URL cannot parse a schemeless string, so HybridAssetLoader.loadAsset threw MalformedURLException, surfacing to JS as "Error loading model". Dev builds were unaffected because Metro serves assets over http://. Fix: detect the scheme on the incoming path. http://, https://, and file:// continue to use URL(path).readBytes() (unchanged). For all other paths (schemeless res/raw identifiers), resolve the resource id via NitroModules.applicationContext and read it with Resources.openRawResource(). This restores the v2.x behaviour for bundled models without changing the public API or the URL/file paths. iOS is unaffected (HybridAssetLoader.swift uses a different code path). --- .../margelo/nitro/tflite/HybridAssetLoader.kt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/margelo/nitro/tflite/HybridAssetLoader.kt b/android/src/main/java/com/margelo/nitro/tflite/HybridAssetLoader.kt index c2360f5a..3b67170a 100644 --- a/android/src/main/java/com/margelo/nitro/tflite/HybridAssetLoader.kt +++ b/android/src/main/java/com/margelo/nitro/tflite/HybridAssetLoader.kt @@ -2,6 +2,7 @@ package com.margelo.nitro.tflite import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.NitroModules import com.margelo.nitro.core.ArrayBuffer import com.margelo.nitro.core.Promise import java.net.URL @@ -11,7 +12,21 @@ import java.net.URL class HybridAssetLoader : HybridAssetLoaderSpec() { override fun loadAsset(path: String): Promise { return Promise.async { - val bytes = URL(path).readBytes() + val bytes = if (path.startsWith("http://") || + path.startsWith("https://") || + path.startsWith("file://")) { + URL(path).readBytes() + } else { + // In release builds, RN's AssetSourceResolver returns a bare Android + // resource identifier (e.g. "app_assets_yolo_nas_pose_n_320_gpu_fp16") + // for non-drawable extensions packaged into res/raw. java.net.URL cannot + // read these — resolve via the app Context / Resources instead. + val ctx = NitroModules.applicationContext + ?: throw IllegalStateException("No ReactApplicationContext available to resolve asset: $path") + val resId = ctx.resources.getIdentifier(path, "raw", ctx.packageName) + if (resId == 0) throw IllegalArgumentException("Asset not found in res/raw: $path") + ctx.resources.openRawResource(resId).use { it.readBytes() } + } return@async ArrayBuffer.copy(bytes) } }