@capgo/native-audio 6.1.35 → 6.2.0

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.
@@ -20,6 +20,7 @@ import android.content.Context;
20
20
  import android.content.res.AssetFileDescriptor;
21
21
  import android.content.res.AssetManager;
22
22
  import android.media.AudioManager;
23
+ import android.net.Uri;
23
24
  import android.os.Build;
24
25
  import android.os.ParcelFileDescriptor;
25
26
  import android.util.Log;
@@ -419,13 +420,15 @@ public class NativeAudio
419
420
  private void preloadAsset(PluginCall call) {
420
421
  double volume = 1.0;
421
422
  int audioChannelNum = 1;
423
+ JSObject status = new JSObject();
424
+ status.put("STATUS", "OK");
422
425
 
423
426
  try {
424
427
  initSoundPool();
425
428
 
426
429
  String audioId = call.getString(ASSET_ID);
427
430
 
428
- boolean isUrl = call.getBoolean("isUrl", false);
431
+ boolean isLocalUrl = Boolean.TRUE.equals(call.getBoolean("isUrl", false));
429
432
 
430
433
  if (!isStringValid(audioId)) {
431
434
  call.reject(ERROR_AUDIO_ID_MISSING + " - " + audioId);
@@ -457,7 +460,7 @@ public class NativeAudio
457
460
  }
458
461
 
459
462
  AssetFileDescriptor assetFileDescriptor;
460
- if (isUrl) {
463
+ if (isLocalUrl) {
461
464
  File f = new File(new URI(fullPath));
462
465
  ParcelFileDescriptor p = ParcelFileDescriptor.open(
463
466
  f,
@@ -465,13 +468,41 @@ public class NativeAudio
465
468
  );
466
469
  assetFileDescriptor = new AssetFileDescriptor(p, 0, -1);
467
470
  } else {
468
- // if fullPath dont start with public/ add it
469
- if (!fullPath.startsWith("public/")) {
470
- fullPath = "public/".concat(fullPath);
471
+ try {
472
+ Uri uri = Uri.parse(fullPath); // Now Uri class should be recognized
473
+ if (
474
+ uri.getScheme() != null &&
475
+ (
476
+ uri.getScheme().equals("http") ||
477
+ uri.getScheme().equals("https")
478
+ )
479
+ ) {
480
+ // It's a remote URL
481
+ RemoteAudioAsset remoteAudioAsset = new RemoteAudioAsset(
482
+ this,
483
+ audioId,
484
+ uri,
485
+ audioChannelNum,
486
+ (float) volume
487
+ );
488
+ audioAssetList.put(audioId, remoteAudioAsset);
489
+ call.resolve(status);
490
+ return;
491
+ } else {
492
+ // It's a local file path
493
+ // Check if fullPath starts with "public/" and prepend if necessary
494
+ if (!fullPath.startsWith("public/")) {
495
+ fullPath = "public/".concat(fullPath);
496
+ }
497
+ Context ctx = getContext().getApplicationContext(); // Use getContext() directly
498
+ AssetManager am = ctx.getResources().getAssets();
499
+ // Remove the redefinition of assetFileDescriptor
500
+ assetFileDescriptor = am.openFd(fullPath);
501
+ }
502
+ } catch (Exception e) {
503
+ call.reject("Error loading audio", e);
504
+ return;
471
505
  }
472
- Context ctx = (Application) this.getContext().getApplicationContext();
473
- AssetManager am = ctx.getResources().getAssets();
474
- assetFileDescriptor = am.openFd(fullPath);
475
506
  }
476
507
 
477
508
  AudioAsset asset = new AudioAsset(
@@ -483,8 +514,6 @@ public class NativeAudio
483
514
  );
484
515
  audioAssetList.put(audioId, asset);
485
516
 
486
- JSObject status = new JSObject();
487
- status.put("STATUS", "OK");
488
517
  call.resolve(status);
489
518
  } else {
490
519
  call.reject(ERROR_AUDIO_EXISTS);
@@ -0,0 +1,87 @@
1
+ package ee.forgr.audio;
2
+
3
+ import android.media.MediaPlayer;
4
+ import android.net.Uri;
5
+
6
+ public class RemoteAudioAsset extends AudioAsset {
7
+
8
+ private MediaPlayer mediaPlayer;
9
+
10
+ public RemoteAudioAsset(
11
+ NativeAudio owner,
12
+ String assetId,
13
+ Uri uri,
14
+ int audioChannelNum,
15
+ float volume
16
+ ) throws Exception {
17
+ super(owner, assetId, null, audioChannelNum, volume);
18
+ mediaPlayer = new MediaPlayer();
19
+ mediaPlayer.setDataSource(owner.getContext(), uri);
20
+ mediaPlayer.setVolume(volume, volume);
21
+ mediaPlayer.prepareAsync(); // Prepare asynchronously to not block the main thread
22
+ }
23
+
24
+ @Override
25
+ public void play(Double time) throws Exception {
26
+ if (mediaPlayer != null) {
27
+ if (time != null) {
28
+ mediaPlayer.seekTo((int) (time * 1000));
29
+ }
30
+ mediaPlayer.start();
31
+ } else {
32
+ throw new Exception("MediaPlayer is null");
33
+ }
34
+ }
35
+
36
+ @Override
37
+ public boolean pause() throws Exception {
38
+ if (mediaPlayer != null && mediaPlayer.isPlaying()) {
39
+ mediaPlayer.pause();
40
+ return true; // Return true to indicate that the audio was paused
41
+ }
42
+ return false;
43
+ }
44
+
45
+ @Override
46
+ public void resume() throws Exception {
47
+ if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
48
+ mediaPlayer.start();
49
+ }
50
+ }
51
+
52
+ @Override
53
+ public void stop() throws Exception {
54
+ if (mediaPlayer != null) {
55
+ mediaPlayer.stop();
56
+ mediaPlayer.prepare(); // Call prepare to reset the MediaPlayer to the Idle state
57
+ }
58
+ }
59
+
60
+ @Override
61
+ public void loop() throws Exception {
62
+ if (mediaPlayer != null) {
63
+ mediaPlayer.setLooping(true);
64
+ mediaPlayer.start();
65
+ }
66
+ }
67
+
68
+ @Override
69
+ public void unload() throws Exception {
70
+ if (mediaPlayer != null) {
71
+ mediaPlayer.release();
72
+ mediaPlayer = null;
73
+ }
74
+ }
75
+
76
+ @Override
77
+ public void setVolume(float volume) throws Exception {
78
+ if (mediaPlayer != null) {
79
+ mediaPlayer.setVolume(volume, volume);
80
+ }
81
+ }
82
+
83
+ @Override
84
+ public boolean isPlaying() throws Exception {
85
+ return mediaPlayer != null && mediaPlayer.isPlaying();
86
+ }
87
+ }
@@ -75,7 +75,7 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
75
75
  player = channels[playIndex]
76
76
  player.currentTime = time
77
77
  player.numberOfLoops = 0
78
- if (delay > 0) {
78
+ if delay > 0 {
79
79
  player.play(atTime: player.deviceCurrentTime + delay)
80
80
  } else {
81
81
  player.play()
@@ -35,12 +35,9 @@ public class NativeAudio: CAPPlugin {
35
35
  }
36
36
 
37
37
  let focus = call.getBool(Constant.FocusAudio) ?? false
38
-
39
38
  do {
40
-
41
39
  if focus {
42
-
43
- try self.session.setCategory(AVAudioSession.Category.playback)
40
+ try self.session.setCategory(AVAudioSession.Category.playback, options: .duckOthers)
44
41
 
45
42
  }
46
43
 
@@ -78,7 +75,7 @@ public class NativeAudio: CAPPlugin {
78
75
 
79
76
  if focus {
80
77
 
81
- try self.session.setCategory(AVAudioSession.Category.ambient)
78
+ try self.session.setCategory(AVAudioSession.Category.ambient, options: .duckOthers)
82
79
 
83
80
  } else {
84
81
 
@@ -263,7 +260,7 @@ public class NativeAudio: CAPPlugin {
263
260
  let channels: Int?
264
261
  let volume: Float?
265
262
  let delay: Float?
266
- let isUrl: Bool?
263
+ var isLocalUrl: Bool = call.getBool("isUrl") ?? false // Existing flag for local URLs
267
264
 
268
265
  if audioId != "" {
269
266
  var assetPath: String = call.getString(Constant.AssetPathKey) ?? ""
@@ -272,12 +269,11 @@ public class NativeAudio: CAPPlugin {
272
269
  volume = call.getFloat("volume") ?? 1.0
273
270
  channels = call.getInt("channels") ?? 1
274
271
  delay = call.getFloat("delay") ?? 1.0
275
- isUrl = call.getBool("isUrl") ?? false
276
272
  } else {
277
273
  channels = 0
278
274
  volume = 0
279
275
  delay = 0
280
- isUrl = false
276
+ isLocalUrl = false
281
277
  }
282
278
 
283
279
  if audioList.isEmpty {
@@ -289,7 +285,12 @@ public class NativeAudio: CAPPlugin {
289
285
  queue.async {
290
286
  if asset == nil {
291
287
  var basePath: String?
292
- if isUrl == false {
288
+ if let url = URL(string: assetPath), url.scheme != nil {
289
+ // Handle remote URL
290
+ let remoteAudioAsset = RemoteAudioAsset(owner: self, withAssetId: audioId, withPath: assetPath, withChannels: channels, withVolume: volume, withFadeDelay: delay)
291
+ self.audioList[audioId] = remoteAudioAsset
292
+ call.resolve()
293
+ } else if isLocalUrl == false {
293
294
  // if assetPath dont start with public/ add it
294
295
  assetPath = assetPath.starts(with: "public/") ? assetPath : "public/" + assetPath
295
296
 
@@ -0,0 +1,74 @@
1
+ import AVFoundation
2
+
3
+ public class RemoteAudioAsset: AudioAsset {
4
+ var playerItem: AVPlayerItem?
5
+ var player: AVPlayer?
6
+
7
+ override init(owner: NativeAudio, withAssetId assetId: String, withPath path: String!, withChannels channels: Int!, withVolume volume: Float!, withFadeDelay delay: Float!) {
8
+ super.init(owner: owner, withAssetId: assetId, withPath: path, withChannels: channels, withVolume: volume, withFadeDelay: delay)
9
+
10
+ if let url = URL(string: path) {
11
+ self.playerItem = AVPlayerItem(url: url)
12
+ self.player = AVPlayer(playerItem: self.playerItem)
13
+ self.player?.volume = volume
14
+ }
15
+ }
16
+
17
+ override func play(time: TimeInterval, delay: TimeInterval) {
18
+ guard let player = self.player else { return }
19
+ if delay > 0 {
20
+ // Calculate the future time to play
21
+ let timeToPlay = CMTimeAdd(CMTimeMakeWithSeconds(player.currentTime().seconds, preferredTimescale: 1), CMTimeMakeWithSeconds(delay, preferredTimescale: 1))
22
+ player.seek(to: timeToPlay)
23
+ } else {
24
+ player.seek(to: CMTimeMakeWithSeconds(time, preferredTimescale: 1))
25
+ }
26
+ player.play()
27
+ }
28
+
29
+ override func pause() {
30
+ player?.pause()
31
+ }
32
+
33
+ override func resume() {
34
+ player?.play()
35
+ }
36
+
37
+ override func stop() {
38
+ player?.pause()
39
+ player?.seek(to: CMTime.zero)
40
+ }
41
+
42
+ override func loop() {
43
+ player?.actionAtItemEnd = .none
44
+ NotificationCenter.default.addObserver(self,
45
+ selector: #selector(playerItemDidReachEnd(notification:)),
46
+ name: .AVPlayerItemDidPlayToEndTime,
47
+ object: player?.currentItem)
48
+ player?.play()
49
+ }
50
+
51
+ @objc func playerItemDidReachEnd(notification: Notification) {
52
+ player?.seek(to: CMTime.zero)
53
+ player?.play()
54
+ }
55
+
56
+ override func unload() {
57
+ stop()
58
+ NotificationCenter.default.removeObserver(self)
59
+ player = nil
60
+ playerItem = nil
61
+ }
62
+
63
+ override func setVolume(volume: NSNumber!) {
64
+ player?.volume = volume.floatValue
65
+ }
66
+
67
+ override func setRate(rate: NSNumber!) {
68
+ player?.rate = rate.floatValue
69
+ }
70
+
71
+ override func isPlaying() -> Bool {
72
+ return player?.timeControlStatus == .playing
73
+ }
74
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/native-audio",
3
- "version": "6.1.35",
3
+ "version": "6.2.0",
4
4
  "description": "A native plugin for native audio engine",
5
5
  "main": "dist/plugin.js",
6
6
  "module": "dist/esm/index.js",