@capgo/native-audio 8.3.3 → 8.3.5
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.
|
@@ -101,6 +101,7 @@ public class NativeAudio extends Plugin implements AudioManager.OnAudioFocusChan
|
|
|
101
101
|
private String currentlyPlayingAssetId;
|
|
102
102
|
private static final int NOTIFICATION_ID = 1001;
|
|
103
103
|
private static final String CHANNEL_ID = "native_audio_channel";
|
|
104
|
+
private static final int MAX_NOTIFICATION_ARTWORK_SIZE = 512;
|
|
104
105
|
|
|
105
106
|
// Track playOnce assets for automatic cleanup
|
|
106
107
|
private Set<String> playOnceAssets = new HashSet<>();
|
|
@@ -1633,16 +1634,40 @@ public class NativeAudio extends Plugin implements AudioManager.OnAudioFocusChan
|
|
|
1633
1634
|
Uri uri = Uri.parse(urlString);
|
|
1634
1635
|
Bitmap bitmap = null;
|
|
1635
1636
|
|
|
1637
|
+
// Configure BitmapFactory options to decode at full resolution
|
|
1638
|
+
BitmapFactory.Options options = new BitmapFactory.Options();
|
|
1639
|
+
options.inScaled = false; // Disable density-based scaling
|
|
1640
|
+
options.inPreferredConfig = Bitmap.Config.ARGB_8888; // Use high quality format
|
|
1641
|
+
|
|
1636
1642
|
if (uri.getScheme() == null || uri.getScheme().equals("file")) {
|
|
1637
1643
|
// Local file
|
|
1638
1644
|
File file = new File(uri.getPath());
|
|
1639
1645
|
if (file.exists()) {
|
|
1640
|
-
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
|
|
1646
|
+
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
|
|
1641
1647
|
}
|
|
1642
1648
|
} else {
|
|
1643
1649
|
// Remote URL
|
|
1644
1650
|
URL url = new URL(urlString);
|
|
1645
|
-
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
|
|
1651
|
+
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream(), null, options);
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
// Resize to optimal notification size if the bitmap is too large
|
|
1655
|
+
// Android notifications typically display artwork at around 128-256dp
|
|
1656
|
+
// We target 512px as a good balance between quality and memory usage
|
|
1657
|
+
if (bitmap != null && bitmap.getWidth() > 0 && bitmap.getHeight() > 0) {
|
|
1658
|
+
if (bitmap.getWidth() > MAX_NOTIFICATION_ARTWORK_SIZE || bitmap.getHeight() > MAX_NOTIFICATION_ARTWORK_SIZE) {
|
|
1659
|
+
float scale = Math.min(
|
|
1660
|
+
(float) MAX_NOTIFICATION_ARTWORK_SIZE / bitmap.getWidth(),
|
|
1661
|
+
(float) MAX_NOTIFICATION_ARTWORK_SIZE / bitmap.getHeight()
|
|
1662
|
+
);
|
|
1663
|
+
int newWidth = Math.round(bitmap.getWidth() * scale);
|
|
1664
|
+
int newHeight = Math.round(bitmap.getHeight() * scale);
|
|
1665
|
+
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
|
|
1666
|
+
if (scaledBitmap != null) {
|
|
1667
|
+
bitmap.recycle(); // Free memory from original bitmap
|
|
1668
|
+
bitmap = scaledBitmap;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1646
1671
|
}
|
|
1647
1672
|
|
|
1648
1673
|
Bitmap finalBitmap = bitmap;
|
|
@@ -113,10 +113,9 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
|
113
113
|
|
|
114
114
|
func getCurrentTime() -> TimeInterval {
|
|
115
115
|
var result: TimeInterval = 0
|
|
116
|
-
owner?.
|
|
117
|
-
guard
|
|
118
|
-
|
|
119
|
-
result = channels[playIndex].currentTime
|
|
116
|
+
owner?.readOnAudioQueue {
|
|
117
|
+
guard !self.channels.isEmpty, self.playIndex < self.channels.count else { return }
|
|
118
|
+
result = self.channels[self.playIndex].currentTime
|
|
120
119
|
}
|
|
121
120
|
return result
|
|
122
121
|
}
|
|
@@ -313,9 +312,8 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
|
313
312
|
|
|
314
313
|
func isPlaying() -> Bool {
|
|
315
314
|
var result = false
|
|
316
|
-
owner?.
|
|
317
|
-
|
|
318
|
-
result = channels.contains(where: { $0.isPlaying })
|
|
315
|
+
owner?.readOnAudioQueue {
|
|
316
|
+
result = self.channels.contains(where: { $0.isPlaying })
|
|
319
317
|
}
|
|
320
318
|
return result
|
|
321
319
|
}
|
|
@@ -12,7 +12,7 @@ enum MyError: Error {
|
|
|
12
12
|
@objc(NativeAudio)
|
|
13
13
|
// swiftlint:disable:next type_body_length
|
|
14
14
|
public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
15
|
-
private let pluginVersion: String = "8.3.
|
|
15
|
+
private let pluginVersion: String = "8.3.5"
|
|
16
16
|
public let identifier = "NativeAudio"
|
|
17
17
|
public let jsName = "NativeAudio"
|
|
18
18
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -1279,6 +1279,15 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
|
1279
1279
|
}
|
|
1280
1280
|
}
|
|
1281
1281
|
|
|
1282
|
+
/// Use this for read-only access to shared state — avoids the .barrier write lock
|
|
1283
|
+
/// that `executeOnAudioQueue` applies, preventing deadlocks with third-party SDKs.
|
|
1284
|
+
internal func readOnAudioQueue<T>(_ block: () -> T) -> T {
|
|
1285
|
+
if DispatchQueue.getSpecific(key: queueKey) != nil {
|
|
1286
|
+
return block()
|
|
1287
|
+
}
|
|
1288
|
+
return audioQueue.sync { block() }
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1282
1291
|
@objc func notifyCurrentTime(_ asset: AudioAsset) {
|
|
1283
1292
|
audioQueue.sync {
|
|
1284
1293
|
let rawTime = asset.getCurrentTime()
|