@capgo/native-audio 6.1.35 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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",