feat: improve background streaming handler with microphone management
- Enhanced BackgroundStreamingHandler to manage microphone streams effectively during background execution. - Introduced VoiceBackgroundAudioManager for better audio session handling, ensuring proper activation and deactivation based on microphone usage. - Updated startBackgroundExecution method to handle microphone requirements dynamically, improving resource management. - Ensured microphone streams are cleared appropriately when stopping background execution, enhancing overall stability.
This commit is contained in:
@@ -266,7 +266,9 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startBackgroundExecution(streamIds: List<String>, requiresMic: Boolean) {
|
private fun startBackgroundExecution(streamIds: List<String>, requiresMic: Boolean) {
|
||||||
|
activeStreams.clear()
|
||||||
activeStreams.addAll(streamIds)
|
activeStreams.addAll(streamIds)
|
||||||
|
streamsRequiringMic.retainAll(activeStreams)
|
||||||
if (requiresMic) {
|
if (requiresMic) {
|
||||||
streamsRequiringMic.addAll(streamIds)
|
streamsRequiringMic.addAll(streamIds)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,55 @@
|
|||||||
|
import AVFoundation
|
||||||
import Flutter
|
import Flutter
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
final class VoiceBackgroundAudioManager {
|
||||||
|
static let shared = VoiceBackgroundAudioManager()
|
||||||
|
|
||||||
|
private var isActive = false
|
||||||
|
|
||||||
|
private init() {}
|
||||||
|
|
||||||
|
func activate() {
|
||||||
|
guard !isActive else { return }
|
||||||
|
|
||||||
|
let session = AVAudioSession.sharedInstance()
|
||||||
|
do {
|
||||||
|
try session.setCategory(
|
||||||
|
.playAndRecord,
|
||||||
|
mode: .voiceChat,
|
||||||
|
options: [
|
||||||
|
.allowBluetooth,
|
||||||
|
.allowBluetoothA2DP,
|
||||||
|
.mixWithOthers,
|
||||||
|
.defaultToSpeaker,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
try session.setActive(true, options: .notifyOthersOnDeactivation)
|
||||||
|
isActive = true
|
||||||
|
} catch {
|
||||||
|
print("VoiceBackgroundAudioManager: Failed to activate audio session: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deactivate() {
|
||||||
|
guard isActive else { return }
|
||||||
|
|
||||||
|
let session = AVAudioSession.sharedInstance()
|
||||||
|
do {
|
||||||
|
try session.setActive(false, options: .notifyOthersOnDeactivation)
|
||||||
|
} catch {
|
||||||
|
print("VoiceBackgroundAudioManager: Failed to deactivate audio session: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Background streaming handler class
|
// Background streaming handler class
|
||||||
class BackgroundStreamingHandler: NSObject {
|
class BackgroundStreamingHandler: NSObject {
|
||||||
private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
|
private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
|
||||||
private var activeStreams: Set<String> = []
|
private var activeStreams: Set<String> = []
|
||||||
|
private var microphoneStreams: Set<String> = []
|
||||||
private var channel: FlutterMethodChannel?
|
private var channel: FlutterMethodChannel?
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
@@ -47,7 +92,8 @@ class BackgroundStreamingHandler: NSObject {
|
|||||||
case "startBackgroundExecution":
|
case "startBackgroundExecution":
|
||||||
if let args = call.arguments as? [String: Any],
|
if let args = call.arguments as? [String: Any],
|
||||||
let streamIds = args["streamIds"] as? [String] {
|
let streamIds = args["streamIds"] as? [String] {
|
||||||
startBackgroundExecution(streamIds: streamIds)
|
let requiresMic = args["requiresMicrophone"] as? Bool ?? false
|
||||||
|
startBackgroundExecution(streamIds: streamIds, requiresMic: requiresMic)
|
||||||
result(nil)
|
result(nil)
|
||||||
} else {
|
} else {
|
||||||
result(FlutterError(code: "INVALID_ARGS", message: "Invalid arguments", details: nil))
|
result(FlutterError(code: "INVALID_ARGS", message: "Invalid arguments", details: nil))
|
||||||
@@ -83,20 +129,29 @@ class BackgroundStreamingHandler: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startBackgroundExecution(streamIds: [String]) {
|
private func startBackgroundExecution(streamIds: [String], requiresMic: Bool) {
|
||||||
activeStreams = Set(streamIds)
|
activeStreams = Set(streamIds)
|
||||||
|
if requiresMic {
|
||||||
|
microphoneStreams = microphoneStreams.union(streamIds)
|
||||||
|
VoiceBackgroundAudioManager.shared.activate()
|
||||||
|
}
|
||||||
|
|
||||||
if UIApplication.shared.applicationState == .background {
|
if UIApplication.shared.applicationState == .background {
|
||||||
startBackgroundTask()
|
startBackgroundTask()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func stopBackgroundExecution(streamIds: [String]) {
|
private func stopBackgroundExecution(streamIds: [String]) {
|
||||||
streamIds.forEach { activeStreams.remove($0) }
|
streamIds.forEach { activeStreams.remove($0) }
|
||||||
|
streamIds.forEach { microphoneStreams.remove($0) }
|
||||||
|
|
||||||
if activeStreams.isEmpty {
|
if activeStreams.isEmpty {
|
||||||
endBackgroundTask()
|
endBackgroundTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if microphoneStreams.isEmpty {
|
||||||
|
VoiceBackgroundAudioManager.shared.deactivate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startBackgroundTask() {
|
private func startBackgroundTask() {
|
||||||
@@ -119,6 +174,10 @@ class BackgroundStreamingHandler: NSObject {
|
|||||||
endBackgroundTask()
|
endBackgroundTask()
|
||||||
startBackgroundTask()
|
startBackgroundTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !microphoneStreams.isEmpty {
|
||||||
|
VoiceBackgroundAudioManager.shared.activate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func saveStreamStates(_ states: [[String: Any]]) {
|
private func saveStreamStates(_ states: [[String: Any]]) {
|
||||||
@@ -147,6 +206,7 @@ class BackgroundStreamingHandler: NSObject {
|
|||||||
deinit {
|
deinit {
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
endBackgroundTask()
|
endBackgroundTask()
|
||||||
|
VoiceBackgroundAudioManager.shared.deactivate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user