diff --git a/apps/common-app/src/examples/AudioFile/AudioFile.tsx b/apps/common-app/src/examples/AudioFile/AudioFile.tsx
index ceee2d6c3..099f6ed91 100644
--- a/apps/common-app/src/examples/AudioFile/AudioFile.tsx
+++ b/apps/common-app/src/examples/AudioFile/AudioFile.tsx
@@ -59,6 +59,7 @@ const AudioFile: FC = () => {
'remotePlay',
() => {
AudioPlayer.play();
+ setIsPlaying(true);
}
);
@@ -66,6 +67,7 @@ const AudioFile: FC = () => {
'remotePause',
() => {
AudioPlayer.pause();
+ setIsPlaying(false);
}
);
diff --git a/apps/fabric-example/android/app/src/main/AndroidManifest.xml b/apps/fabric-example/android/app/src/main/AndroidManifest.xml
index 4d01862b1..444e9f223 100644
--- a/apps/fabric-example/android/app/src/main/AndroidManifest.xml
+++ b/apps/fabric-example/android/app/src/main/AndroidManifest.xml
@@ -5,7 +5,6 @@
-
-
+
start();
auto result = mStream_->requestStart();
return result == oboe::Result::OK;
}
@@ -56,6 +59,7 @@ bool AudioPlayer::start() {
void AudioPlayer::stop() {
if (mStream_) {
+ nativeAudioPlayer_->stop();
mStream_->requestStop();
}
}
diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h
index 1a797877f..5283a4316 100644
--- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h
+++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h
@@ -5,6 +5,8 @@
#include
#include
+#include
+
namespace audioapi {
using namespace oboe;
@@ -19,13 +21,18 @@ class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback {
float sampleRate,
int channelCount);
+ ~AudioPlayer() override {
+ nativeAudioPlayer_.release();
+ cleanup();
+ }
+
bool start();
void stop();
bool resume();
void suspend();
void cleanup();
- bool isRunning() const;
+ [[nodiscard]] bool isRunning() const;
DataCallbackResult onAudioReady(
AudioStream *oboeStream,
@@ -44,6 +51,8 @@ class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback {
int channelCount_;
bool openAudioStream();
+
+ facebook::jni::global_ref nativeAudioPlayer_;
};
} // namespace audioapi
diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/NativeAudioPlayer.hpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/NativeAudioPlayer.hpp
new file mode 100644
index 000000000..54d3b490b
--- /dev/null
+++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/NativeAudioPlayer.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace audioapi {
+
+using namespace facebook;
+using namespace react;
+
+class NativeAudioPlayer : public jni::JavaClass {
+ public:
+ static auto constexpr kJavaDescriptor =
+ "Lcom/swmansion/audioapi/core/NativeAudioPlayer;";
+
+ static jni::local_ref create() {
+ return newInstance();
+ }
+
+ void start() {
+ static const auto method = javaClassStatic()->getMethod("start");
+ method(self());
+ }
+
+ void stop() {
+ static const auto method = javaClassStatic()->getMethod("stop");
+ method(self());
+ }
+};
+
+} // namespace audioapi
diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/core/NativeAudioPlayer.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/core/NativeAudioPlayer.kt
new file mode 100644
index 000000000..ee177c337
--- /dev/null
+++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/core/NativeAudioPlayer.kt
@@ -0,0 +1,24 @@
+package com.swmansion.audioapi.core
+
+import com.facebook.common.internal.DoNotStrip
+import com.swmansion.audioapi.system.MediaSessionManager
+
+@DoNotStrip
+class NativeAudioPlayer {
+ private var sourceNodeId: String? = null
+
+ @DoNotStrip
+ fun start() {
+ this.sourceNodeId = MediaSessionManager.attachAudioPlayer(this)
+ MediaSessionManager.startForegroundServiceIfNecessary()
+ }
+
+ @DoNotStrip
+ fun stop() {
+ this.sourceNodeId?.let {
+ MediaSessionManager.detachAudioPlayer(it)
+ this.sourceNodeId = null
+ }
+ MediaSessionManager.stopForegroundServiceIfNecessary()
+ }
+}
diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt
index 6d3bcd578..be1b20629 100644
--- a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt
+++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt
@@ -122,7 +122,7 @@ class LockScreenManager(
)
nb.setLargeIcon(bitmap)
- mediaNotificationManager.get()?.show(nb, isPlaying)
+ mediaNotificationManager.get()?.updateNotification(nb, isPlaying)
artworkThread = null
} catch (ex: Exception) {
@@ -167,14 +167,14 @@ class LockScreenManager(
mediaSession.get()?.setMetadata(md.build())
mediaSession.get()?.setActive(true)
- mediaNotificationManager.get()?.show(nb, isPlaying)
+ mediaNotificationManager.get()?.updateNotification(nb, isPlaying)
}
fun resetLockScreenInfo() {
if (artworkThread != null && artworkThread!!.isAlive) artworkThread!!.interrupt()
artworkThread = null
- mediaNotificationManager.get()?.hide()
+ mediaNotificationManager.get()?.cancelNotification()
mediaSession.get()?.setActive(false)
}
@@ -235,7 +235,7 @@ class LockScreenManager(
updateNotificationMediaStyle()
if (mediaSession.get()?.isActive == true) {
- mediaNotificationManager.get()?.show(nb, isPlaying)
+ mediaNotificationManager.get()?.updateNotification(nb, isPlaying)
}
}
diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt
index 41b770717..5c046338b 100644
--- a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt
+++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt
@@ -1,21 +1,22 @@
package com.swmansion.audioapi.system
+import android.Manifest
import android.annotation.SuppressLint
import android.app.Notification
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
+import android.content.pm.ServiceInfo
import android.content.res.Resources
-import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.provider.ContactsContract
import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log
import android.view.KeyEvent
+import androidx.annotation.RequiresPermission
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
-import androidx.core.content.ContextCompat
import com.facebook.react.bridge.ReactApplicationContext
import com.swmansion.audioapi.R
import java.lang.ref.WeakReference
@@ -23,7 +24,7 @@ import java.lang.ref.WeakReference
class MediaNotificationManager(
private val reactContext: WeakReference,
) {
- private var smallIcon: Int = R.drawable.play
+ private var smallIcon: Int = R.drawable.logo
private var customIcon: Int = 0
private var play: NotificationCompat.Action? = null
@@ -40,6 +41,16 @@ class MediaNotificationManager(
const val MEDIA_BUTTON: String = "audio_manager_media_button"
}
+ enum class ForegroundAction {
+ START_FOREGROUND,
+ STOP_FOREGROUND,
+ ;
+
+ companion object {
+ fun fromAction(action: String?): ForegroundAction? = entries.firstOrNull { it.name == action }
+ }
+ }
+
@SuppressLint("RestrictedApi")
@Synchronized
fun prepareNotification(
@@ -107,34 +118,20 @@ class MediaNotificationManager(
return builder.build()
}
- @SuppressLint("MissingPermission")
+ @RequiresPermission(Manifest.permission.POST_NOTIFICATIONS)
@Synchronized
- fun show(
+ fun updateNotification(
builder: NotificationCompat.Builder?,
isPlaying: Boolean,
) {
NotificationManagerCompat.from(reactContext.get()!!).notify(
MediaSessionManager.NOTIFICATION_ID,
- prepareNotification(
- builder!!,
- isPlaying,
- ),
+ prepareNotification(builder!!, isPlaying),
)
}
- fun hide() {
+ fun cancelNotification() {
NotificationManagerCompat.from(reactContext.get()!!).cancel(MediaSessionManager.NOTIFICATION_ID)
-
- try {
- val myIntent =
- Intent(
- reactContext.get(),
- NotificationService::class.java,
- )
- reactContext.get()?.stopService(myIntent)
- } catch (e: java.lang.Exception) {
- Log.w("AudioManagerModule", "Error stopping service: ${e.message}")
- }
}
@Synchronized
@@ -182,45 +179,42 @@ class MediaNotificationManager(
return NotificationCompat.Action(icon!!, title, i)
}
- class NotificationService : Service() {
- private val binder = LocalBinder()
+ class AudioForegroundService : Service() {
private var notification: Notification? = null
-
- inner class LocalBinder : Binder() {
- private var weakService: WeakReference? = null
-
- fun onBind(service: NotificationService) {
- weakService = WeakReference(service)
- }
-
- fun getService(): NotificationService? = weakService?.get()
- }
-
- override fun onBind(intent: Intent): IBinder {
- binder.onBind(this)
- return binder
- }
-
- fun forceForeground() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- val intent = Intent(this, NotificationService::class.java)
- ContextCompat.startForegroundService(this, intent)
- notification =
- MediaSessionManager.mediaNotificationManager
- .prepareNotification(NotificationCompat.Builder(this, MediaSessionManager.CHANNEL_ID), false)
- startForeground(MediaSessionManager.NOTIFICATION_ID, notification)
- }
- }
-
- override fun onCreate() {
- super.onCreate()
- try {
- notification =
- MediaSessionManager.mediaNotificationManager
- .prepareNotification(NotificationCompat.Builder(this, MediaSessionManager.CHANNEL_ID), false)
- startForeground(MediaSessionManager.NOTIFICATION_ID, notification)
- } catch (ex: Exception) {
- Log.w("AudioManagerModule", "Error starting service: ${ex.message}")
+ private var isServiceStarted = false
+ private val serviceLock = Any()
+
+ override fun onBind(intent: Intent): IBinder? = null
+
+ private fun startForegroundService() {
+ synchronized(serviceLock) {
+ if (!isServiceStarted) {
+ try {
+ notification =
+ MediaSessionManager.mediaNotificationManager
+ .prepareNotification(
+ NotificationCompat.Builder(this, MediaSessionManager.CHANNEL_ID),
+ false,
+ )
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ startForeground(
+ MediaSessionManager.NOTIFICATION_ID,
+ notification!!,
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST,
+ )
+ } else {
+ startForeground(
+ MediaSessionManager.NOTIFICATION_ID,
+ notification,
+ )
+ }
+ isServiceStarted = true
+ } catch (ex: Exception) {
+ Log.e("AudioManagerModule", "Error starting foreground service: ${ex.message}")
+ stopSelf()
+ }
+ }
}
}
@@ -229,26 +223,40 @@ class MediaNotificationManager(
flags: Int,
startId: Int,
): Int {
- onCreate()
+ val action = ForegroundAction.fromAction(intent?.action)
+
+ when (action) {
+ ForegroundAction.START_FOREGROUND -> startForegroundService()
+ ForegroundAction.STOP_FOREGROUND -> stopForegroundService()
+ else -> startForegroundService()
+ }
+
return START_NOT_STICKY
}
+ private fun stopForegroundService() {
+ synchronized(serviceLock) {
+ if (isServiceStarted) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ }
+ isServiceStarted = false
+ stopSelf()
+ }
+ }
+ }
+
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- stopForeground(STOP_FOREGROUND_REMOVE)
- }
- stopSelf()
+ stopForegroundService()
}
override fun onDestroy() {
- super.onDestroy()
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- stopForeground(STOP_FOREGROUND_REMOVE)
+ synchronized(serviceLock) {
+ notification = null
+ isServiceStarted = false
}
-
- stopSelf()
+ super.onDestroy()
}
}
}
diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt
index c877d0b45..5832c56aa 100644
--- a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt
+++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt
@@ -25,7 +25,8 @@ class MediaReceiver(
if (MediaNotificationManager.REMOVE_NOTIFICATION == action) {
if (!checkApp(intent)) return
- mediaNotificationManager.get()?.hide()
+ mediaNotificationManager.get()?.cancelNotification()
+ MediaSessionManager.stopForegroundServiceIfNecessary()
mediaSession.get()?.isActive = false
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("closeNotification", mapOf()) // add to ts events
diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt
index 46bfe6b59..fc5a49466 100644
--- a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt
+++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt
@@ -1,17 +1,14 @@
package com.swmansion.audioapi.system
-import android.content.Intent
-import android.os.Build
import android.os.Bundle
import android.support.v4.media.session.MediaSessionCompat
import android.util.Log
-import androidx.core.app.NotificationManagerCompat
import com.swmansion.audioapi.AudioAPIModule
import java.lang.ref.WeakReference
-import java.util.HashMap
class MediaSessionCallback(
private val audioAPIModule: WeakReference,
+ private val mediaNotificationManager: WeakReference,
) : MediaSessionCompat.Callback() {
override fun onPlay() {
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePlay", mapOf())
@@ -22,13 +19,8 @@ class MediaSessionCallback(
}
override fun onStop() {
- val reactContext = audioAPIModule.get()?.reactContext?.get()!!
- NotificationManagerCompat.from(reactContext).cancel(MediaSessionManager.NOTIFICATION_ID)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- val myIntent =
- Intent(reactContext, MediaNotificationManager.NotificationService::class.java)
- reactContext.stopService(myIntent)
- }
+ mediaNotificationManager.get()?.cancelNotification()
+ MediaSessionManager.stopForegroundServiceIfNecessary()
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteStop", mapOf())
}
diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt
index d50cbd054..7ec82d0b2 100644
--- a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt
+++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt
@@ -3,18 +3,14 @@ package com.swmansion.audioapi.system
import android.Manifest
import android.app.NotificationChannel
import android.app.NotificationManager
-import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
-import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.media.AudioDeviceInfo
import android.media.AudioManager
import android.os.Build
-import android.os.IBinder
import android.support.v4.media.session.MediaSessionCompat
-import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
@@ -24,8 +20,10 @@ import com.facebook.react.bridge.ReadableMap
import com.facebook.react.modules.core.PermissionAwareActivity
import com.facebook.react.modules.core.PermissionListener
import com.swmansion.audioapi.AudioAPIModule
+import com.swmansion.audioapi.core.NativeAudioPlayer
import com.swmansion.audioapi.system.PermissionRequestListener.Companion.RECORDING_REQUEST_CODE
import java.lang.ref.WeakReference
+import java.util.UUID
object MediaSessionManager {
private lateinit var audioAPIModule: WeakReference
@@ -41,31 +39,9 @@ object MediaSessionManager {
private lateinit var volumeChangeListener: VolumeChangeListener
private lateinit var mediaReceiver: MediaReceiver
- private val connection =
- object : ServiceConnection {
- override fun onServiceConnected(
- name: ComponentName,
- service: IBinder,
- ) {
- Log.w("MediaSessionManager", "onServiceConnected")
- val binder = service as MediaNotificationManager.NotificationService.LocalBinder
- val notificationService = binder.getService()
- notificationService?.forceForeground()
- reactContext.get()?.unbindService(this)
- }
-
- override fun onServiceDisconnected(name: ComponentName) {
- Log.w("MediaSessionManager", "Service is disconnected.")
- }
-
- override fun onBindingDied(name: ComponentName) {
- Log.w("MediaSessionManager", "Binding has died.")
- }
-
- override fun onNullBinding(name: ComponentName) {
- Log.w("MediaSessionManager", "Bind was null.")
- }
- }
+ private var isServiceRunning = false
+ private val serviceStateLock = Any()
+ private val nativeAudioPlayers = mutableMapOf()
fun initialize(
audioAPIModule: WeakReference,
@@ -83,8 +59,8 @@ object MediaSessionManager {
this.mediaNotificationManager = MediaNotificationManager(this.reactContext)
this.lockScreenManager = LockScreenManager(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager))
this.mediaReceiver =
- MediaReceiver(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager), this.audioAPIModule)
- this.mediaSession.setCallback(MediaSessionCallback(this.audioAPIModule))
+ MediaReceiver(this.reactContext, WeakReference(this.mediaSession), WeakReference(this.mediaNotificationManager), this.audioAPIModule)
+ this.mediaSession.setCallback(MediaSessionCallback(this.audioAPIModule, WeakReference(this.mediaNotificationManager)))
val filter = IntentFilter()
filter.addAction(MediaNotificationManager.REMOVE_NOTIFICATION)
@@ -106,17 +82,59 @@ object MediaSessionManager {
this.audioFocusListener =
AudioFocusListener(WeakReference(this.audioManager), this.audioAPIModule, WeakReference(this.lockScreenManager))
this.volumeChangeListener = VolumeChangeListener(WeakReference(this.audioManager), this.audioAPIModule)
+ }
- val myIntent = Intent(this.reactContext.get(), MediaNotificationManager.NotificationService::class.java)
+ fun attachAudioPlayer(player: NativeAudioPlayer): String {
+ val uuid = UUID.randomUUID().toString()
+ nativeAudioPlayers[uuid] = player
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- try {
- this.reactContext.get()?.bindService(myIntent, connection, Context.BIND_AUTO_CREATE)
- } catch (ignored: Exception) {
- ContextCompat.startForegroundService(this.reactContext.get()!!, myIntent)
+ return uuid
+ }
+
+ fun detachAudioPlayer(uuid: String) {
+ nativeAudioPlayers.remove(uuid)
+ }
+
+ fun startForegroundServiceIfNecessary() {
+ if (nativeAudioPlayers.isNotEmpty()) {
+ startForegroundService()
+ }
+ }
+
+ fun stopForegroundServiceIfNecessary() {
+ if (nativeAudioPlayers.isEmpty()) {
+ stopForegroundService()
+ }
+ }
+
+ private fun startForegroundService() {
+ synchronized(serviceStateLock) {
+ if (isServiceRunning || reactContext.get() == null) {
+ return
}
- } else {
- this.reactContext.get()?.startService(myIntent)
+
+ val intent = Intent(reactContext.get(), MediaNotificationManager.AudioForegroundService::class.java)
+ intent.action = MediaNotificationManager.ForegroundAction.START_FOREGROUND.name
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ ContextCompat.startForegroundService(reactContext.get()!!, intent)
+ } else {
+ reactContext.get()!!.startService(intent)
+ }
+ isServiceRunning = true
+ }
+ }
+
+ private fun stopForegroundService() {
+ synchronized(serviceStateLock) {
+ if (!isServiceRunning || reactContext.get() == null) {
+ return
+ }
+
+ val intent = Intent(reactContext.get(), MediaNotificationManager.AudioForegroundService::class.java)
+ intent.action = MediaNotificationManager.ForegroundAction.STOP_FOREGROUND.name
+ reactContext.get()!!.startService(intent)
+ isServiceRunning = false
}
}
diff --git a/packages/react-native-audio-api/android/src/main/res/drawable/logo.xml b/packages/react-native-audio-api/android/src/main/res/drawable/logo.xml
new file mode 100644
index 000000000..6eb728c9b
--- /dev/null
+++ b/packages/react-native-audio-api/android/src/main/res/drawable/logo.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioContextHostObject.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioContextHostObject.h
index 5af7b366c..8d581a40e 100644
--- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioContextHostObject.h
+++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioContextHostObject.h
@@ -25,45 +25,39 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
}
JSI_HOST_FUNCTION(close) {
- auto promise = promiseVendor_->createPromise([this](std::shared_ptr promise) {
- std::thread([this, promise = std::move(promise)]() {
- auto audioContext = std::static_pointer_cast(context_);
- audioContext->close();
+ auto audioContext = std::static_pointer_cast(context_);
+ auto promise = promiseVendor_->createPromise([audioContext](const std::shared_ptr& promise) {
+ audioContext->close();
- promise->resolve([](jsi::Runtime &runtime) {
- return jsi::Value::undefined();
- });
- }).detach();
+ promise->resolve([](jsi::Runtime &runtime) {
+ return jsi::Value::undefined();
+ });
});
return promise;
}
JSI_HOST_FUNCTION(resume) {
- auto promise = promiseVendor_->createPromise([this](std::shared_ptr promise) {
- std::thread([this, promise = std::move(promise)]() {
- auto audioContext = std::static_pointer_cast(context_);
- auto result = audioContext->resume();
+ auto audioContext = std::static_pointer_cast(context_);
+ auto promise = promiseVendor_->createPromise([audioContext](const std::shared_ptr& promise) {
+ auto result = audioContext->resume();
- promise->resolve([result](jsi::Runtime &runtime) {
+ promise->resolve([result](jsi::Runtime &runtime) {
return jsi::Value(result);
- });
- }).detach();
+ });
});
return promise;
}
JSI_HOST_FUNCTION(suspend) {
- auto promise = promiseVendor_->createPromise([this](std::shared_ptr promise) {
- std::thread([this, promise = std::move(promise)]() {
- auto audioContext = std::static_pointer_cast(context_);
- auto result = audioContext->suspend();
+ auto audioContext = std::static_pointer_cast(context_);
+ auto promise = promiseVendor_->createPromise([audioContext](const std::shared_ptr& promise) {
+ auto result = audioContext->suspend();
- promise->resolve([result](jsi::Runtime &runtime) {
- return jsi::Value(result);
- });
- }).detach();
+ promise->resolve([result](jsi::Runtime &runtime) {
+ return jsi::Value(result);
+ });
});
return promise;
diff --git a/packages/react-native-audio-api/src/plugin/withAudioAPI.ts b/packages/react-native-audio-api/src/plugin/withAudioAPI.ts
index e025283bb..973393f22 100644
--- a/packages/react-native-audio-api/src/plugin/withAudioAPI.ts
+++ b/packages/react-native-audio-api/src/plugin/withAudioAPI.ts
@@ -71,7 +71,7 @@ const withForegroundService: ConfigPlugin = (
const serviceElement = {
$: {
'android:name':
- 'com.swmansion.audioapi.system.MediaNotificationManager$NotificationService',
+ 'com.swmansion.audioapi.system.MediaNotificationManager$AudioForegroundService',
'android:stopWithTask': 'true',
'android:foregroundServiceType': SFTypes,
},