react-native-davoice-tts 1.0.275 → 1.0.277

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ require 'json'
2
2
 
3
3
  Pod::Spec.new do |s|
4
4
  s.name = "TTSRNBridge"
5
- s.version = "1.0.148" # Update to your package version
5
+ s.version = "1.0.150" # Update to your package version
6
6
  s.summary = "TTS for React Native."
7
7
  s.description = <<-DESC
8
8
  A React Native module for tts .
@@ -1 +1 @@
1
- 0f748bfafef7fdc5d03bbefdb41bfcdd tts-1.0.0.aar
1
+ faa5cade26dcaf91c23989be5442e102 tts-1.0.0.aar
@@ -1 +1 @@
1
- 39cfd203581433a5e0e36e57abd911bcb30ea922 tts-1.0.0.aar
1
+ d00ea3703391db2243e11526aebb47f37e146b97 tts-1.0.0.aar
@@ -24,10 +24,14 @@ import android.content.res.AssetFileDescriptor;
24
24
  import java.io.IOException;
25
25
  import java.net.URL;
26
26
  import java.net.URLConnection;
27
+ import com.google.android.play.core.assetpacks.AssetPackLocation;
28
+ import com.google.android.play.core.assetpacks.AssetPackManager;
29
+ import com.google.android.play.core.assetpacks.AssetPackManagerFactory;
27
30
 
28
31
 
29
32
  import com.davoice.tts.DaVoiceTTSInterface;
30
33
 
34
+
31
35
  public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
32
36
 
33
37
  private final DaVoiceTTSInterface tts;
@@ -160,13 +164,19 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
160
164
  !s.toLowerCase(Locale.US).startsWith("file:") &&
161
165
  !s.toLowerCase(Locale.US).startsWith("content:") &&
162
166
  !s.toLowerCase(Locale.US).startsWith("asset:") &&
163
- // ✅ IMPORTANT: RN release resource names are NOT AssetManager assets
164
- !s.startsWith("assets_");
167
+ // ✅ IMPORTANT: RN release resource names are NOT AssetManager assets (res/raw)
168
+ !s.startsWith("assets_") && !s.startsWith("src_assets_");
169
+
165
170
 
166
171
  final String modelName;
167
172
  if (looksLikePlainAssetPath) {
168
- // PASS THROUGH (old working behavior)
169
- modelName = s;
173
+ File f = resolvePlainModelToFile(s, modelExt != null ? modelExt : "onnx");
174
+ if (f != null) {
175
+ modelName = f.getAbsolutePath(); // pass a real filesystem path to the engine
176
+ } else {
177
+ // Last resort: keep old behavior (in case engine itself can open via AssetManager)
178
+ modelName = s;
179
+ }
170
180
  } else {
171
181
  // Use provided extension when RN gave us assets_* (no ext), otherwise fall back safely.
172
182
  final String ext = (modelExt != null && !modelExt.isEmpty()) ? modelExt : "onnx";
@@ -197,6 +207,53 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
197
207
  }
198
208
  }
199
209
 
210
+ /** models_pack → absolute file (if installed), else null */
211
+ @Nullable
212
+ private File getFileFromAssetPack(String relative) {
213
+ try {
214
+ AssetPackManager apm = AssetPackManagerFactory.getInstance(reactCtx.getApplicationContext());
215
+ AssetPackLocation loc = apm.getPackLocation("models_pack");
216
+ if (loc == null) return null;
217
+ String root = loc.assetsPath(); // .../assets
218
+ if (root == null) return null;
219
+
220
+ // Accept both "model.onnx" and "models/model.onnx"
221
+ String rel = relative.startsWith("models/") ? relative : ("models/" + relative);
222
+ File f = new File(root, rel);
223
+ return f.exists() ? f : null;
224
+ } catch (Throwable t) {
225
+ Log.w(TAG, "getFileFromAssetPack failed: " + t.getMessage());
226
+ return null;
227
+ }
228
+ }
229
+
230
+ /** If in res/raw, copy to cache and return File; else null. */
231
+ @Nullable
232
+ private File tryResolveFromResRawToCache(String nameMaybeWithExt, @Nullable String defaultExt) {
233
+ // Accept "model.onnx" or "model"
234
+ String rawName = nameMaybeWithExt;
235
+ if (rawName == null) return null;
236
+ rawName = rawName.trim();
237
+ if (rawName.isEmpty()) return null;
238
+ int dot = rawName.lastIndexOf('.');
239
+ if (dot > 0) rawName = rawName.substring(0, dot);
240
+ return copyRawResourceToCache(rawName, defaultExt);
241
+ }
242
+
243
+ /** For plain names, resolve to an absolute File using res/raw or asset-pack. */
244
+ @Nullable
245
+ private File resolvePlainModelToFile(String plain, @Nullable String defaultExt) {
246
+ // 1) res/raw (RN may map bundled assets there in release)
247
+ File fromRaw = tryResolveFromResRawToCache(plain, defaultExt);
248
+ if (fromRaw != null && fromRaw.exists()) return fromRaw;
249
+
250
+ // 2) fast-follow asset pack
251
+ File fromPack = getFileFromAssetPack(plain);
252
+ if (fromPack != null && fromPack.exists()) return fromPack;
253
+
254
+ return null;
255
+ }
256
+
200
257
  @ReactMethod
201
258
  public void speak(String text, int speakerId, double speed, Promise promise) {
202
259
  try {
@@ -241,6 +298,24 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
241
298
  }
242
299
  }
243
300
 
301
+ private File tryCopyRawToCacheIfExists(String name, @Nullable String defaultExt) {
302
+ if (name == null) return null;
303
+ final String s = name.trim();
304
+ if (s.isEmpty()) return null;
305
+
306
+ // Only reasonable resource entry names (no scheme, no slashes)
307
+ if (s.contains("://") || s.contains("/") || s.contains("\\") || s.startsWith(".")) return null;
308
+
309
+ // IMPORTANT: res/raw entry names have NO extension in Android resources
310
+ // If caller passed "foo.wav", strip extension for resource lookup.
311
+ String rawName = s;
312
+ int dot = rawName.lastIndexOf('.');
313
+ if (dot > 0) rawName = rawName.substring(0, dot);
314
+
315
+ File out = copyRawResourceToCache(rawName, defaultExt);
316
+ return (out != null && out.exists()) ? out : null;
317
+ }
318
+
244
319
  // Resolve pathOrURL -> local readable File (supports http(s), asset:/, file://, plain path)
245
320
  // defaultExt can be "wav", "onnx", etc (used for tmp file naming when extension missing)
246
321
  private File resolveToLocalFileForRead(String pathOrURL, @Nullable String defaultExt) throws Exception {
@@ -248,6 +323,16 @@ public class DaVoiceTTSBridge extends ReactContextBaseJavaModule {
248
323
  final String s = pathOrURL.trim();
249
324
  if (s.isEmpty()) return null;
250
325
 
326
+ // 0) RN bundled assets on Android are usually in res/raw and resolve to a resource entry name
327
+ // like "assets_*" OR "src_assets_*" (no extension). Try res/raw first.
328
+ {
329
+ File out = tryCopyRawToCacheIfExists(s, defaultExt);
330
+ if (out != null) {
331
+ Log.i(TAG, "resolveToLocalFileForRead: copied res/raw '" + s + "' -> " + out.getAbsolutePath());
332
+ return out;
333
+ }
334
+ }
335
+
251
336
  // 0) RN bundled assets resolve to res/raw names like "assets_cashregistersound" (NO extension).
252
337
  // They are NOT APK /assets files. Handle exactly like react-native-sound: Resources.getIdentifier(..., "raw", ...)
253
338
  if (s.startsWith("assets_")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-davoice-tts",
3
- "version": "1.0.275",
3
+ "version": "1.0.277",
4
4
  "description": "tts library for React Native",
5
5
  "main": "tts/index.js",
6
6
  "types": "tts/index.d.ts",
package/speech/index.ts CHANGED
@@ -761,6 +761,11 @@ class Speech {
761
761
  console.log('[Speech.playWav] resolveAssetSource ->', asset);
762
762
 
763
763
  let realPath = asset?.uri ?? pathOrURL;
764
+ if (Platform.OS === 'android' && typeof asset?.uri === 'string') {
765
+ // Pass raw resource entry name through (native will resolve via res/raw)
766
+ realPath = asset.uri;
767
+ }
768
+
764
769
  console.log('[Speech.playWav] resolved realPath:', realPath);
765
770
 
766
771
  if (typeof realPath !== 'string') {