feat: enhance background streaming handler with microphone support
- Updated BackgroundStreamingHandler to include microphone permission handling for background execution. - Modified startBackgroundExecution method to accept a requiresMicrophone parameter, allowing dynamic management of streams requiring microphone access. - Adjusted service intent to pass microphone requirement status, improving service behavior based on app state. - Enhanced VoiceCallService to utilize the new microphone support during voice call streaming, ensuring proper resource management.
This commit is contained in:
@@ -35,7 +35,7 @@ class BackgroundStreamingService : Service() {
|
||||
const val NOTIFICATION_ID = 1001
|
||||
const val ACTION_START = "START_STREAMING"
|
||||
const val ACTION_STOP = "STOP_STREAMING"
|
||||
private const val EXTRA_REQUIRES_MICROPHONE = "requiresMicrophone"
|
||||
const val EXTRA_REQUIRES_MICROPHONE = "requiresMicrophone"
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
@@ -197,6 +197,7 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
||||
private lateinit var sharedPrefs: SharedPreferences
|
||||
|
||||
private val activeStreams = mutableSetOf<String>()
|
||||
private val streamsRequiringMic = mutableSetOf<String>()
|
||||
private var backgroundJob: Job? = null
|
||||
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
|
||||
@@ -219,8 +220,9 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
||||
when (call.method) {
|
||||
"startBackgroundExecution" -> {
|
||||
val streamIds = call.argument<List<String>>("streamIds")
|
||||
val requiresMic = call.argument<Boolean>("requiresMicrophone") ?: false
|
||||
if (streamIds != null) {
|
||||
startBackgroundExecution(streamIds)
|
||||
startBackgroundExecution(streamIds, requiresMic)
|
||||
result.success(null)
|
||||
} else {
|
||||
result.error("INVALID_ARGS", "Stream IDs required", null)
|
||||
@@ -263,8 +265,11 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
||||
}
|
||||
}
|
||||
|
||||
private fun startBackgroundExecution(streamIds: List<String>) {
|
||||
private fun startBackgroundExecution(streamIds: List<String>, requiresMic: Boolean) {
|
||||
activeStreams.addAll(streamIds)
|
||||
if (requiresMic) {
|
||||
streamsRequiringMic.addAll(streamIds)
|
||||
}
|
||||
|
||||
if (activeStreams.isNotEmpty()) {
|
||||
startForegroundService()
|
||||
@@ -274,6 +279,7 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
||||
|
||||
private fun stopBackgroundExecution(streamIds: List<String>) {
|
||||
activeStreams.removeAll(streamIds.toSet())
|
||||
streamsRequiringMic.removeAll(streamIds.toSet())
|
||||
|
||||
if (activeStreams.isEmpty()) {
|
||||
stopForegroundService()
|
||||
@@ -285,6 +291,10 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
||||
try {
|
||||
val serviceIntent = Intent(context, BackgroundStreamingService::class.java)
|
||||
serviceIntent.putExtra("streamCount", activeStreams.size)
|
||||
serviceIntent.putExtra(
|
||||
BackgroundStreamingService.EXTRA_REQUIRES_MICROPHONE,
|
||||
streamsRequiringMic.isNotEmpty(),
|
||||
)
|
||||
serviceIntent.action = BackgroundStreamingService.ACTION_START
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
@@ -296,6 +306,7 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
||||
println("BackgroundStreamingHandler: Failed to start foreground service: ${e.message}")
|
||||
// Clear active streams as we couldn't start the service
|
||||
activeStreams.clear()
|
||||
streamsRequiringMic.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +357,10 @@ class BackgroundStreamingHandler(private val activity: MainActivity) : MethodCal
|
||||
val serviceIntent = Intent(context, BackgroundStreamingService::class.java)
|
||||
serviceIntent.action = "KEEP_ALIVE"
|
||||
serviceIntent.putExtra("streamCount", activeStreams.size)
|
||||
serviceIntent.putExtra(
|
||||
BackgroundStreamingService.EXTRA_REQUIRES_MICROPHONE,
|
||||
streamsRequiringMic.isNotEmpty(),
|
||||
)
|
||||
context.startService(serviceIntent)
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,10 @@ class BackgroundStreamingHandler {
|
||||
}
|
||||
|
||||
/// Start background execution for given stream IDs
|
||||
Future<void> startBackgroundExecution(List<String> streamIds) async {
|
||||
Future<void> startBackgroundExecution(
|
||||
List<String> streamIds, {
|
||||
bool requiresMicrophone = false,
|
||||
}) async {
|
||||
if (!Platform.isIOS && !Platform.isAndroid) return;
|
||||
|
||||
_activeStreamIds.addAll(streamIds);
|
||||
@@ -69,6 +72,7 @@ class BackgroundStreamingHandler {
|
||||
try {
|
||||
await _channel.invokeMethod('startBackgroundExecution', {
|
||||
'streamIds': streamIds,
|
||||
'requiresMicrophone': requiresMicrophone,
|
||||
});
|
||||
|
||||
DebugLogger.stream(
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
|
||||
import '../../../core/providers/app_providers.dart';
|
||||
import '../../../core/services/background_streaming_handler.dart';
|
||||
import '../../../core/services/socket_service.dart';
|
||||
import '../../../core/utils/markdown_to_text.dart';
|
||||
import '../providers/chat_providers.dart';
|
||||
@@ -24,6 +25,8 @@ enum VoiceCallState {
|
||||
}
|
||||
|
||||
class VoiceCallService {
|
||||
static const String _voiceCallStreamId = 'voice-call';
|
||||
|
||||
final VoiceInputService _voiceInput;
|
||||
final TextToSpeechService _tts;
|
||||
final SocketService _socketService;
|
||||
@@ -130,6 +133,10 @@ class VoiceCallService {
|
||||
throw Exception('Failed to establish socket connection');
|
||||
}
|
||||
|
||||
await BackgroundStreamingHandler.instance.startBackgroundExecution(const [
|
||||
_voiceCallStreamId,
|
||||
], requiresMicrophone: true);
|
||||
|
||||
// Set up socket event listener for assistant responses
|
||||
_socketSubscription = _socketService.addChatEventHandler(
|
||||
conversationId: conversationId,
|
||||
@@ -144,6 +151,9 @@ class VoiceCallService {
|
||||
_updateState(VoiceCallState.error);
|
||||
await WakelockPlus.disable();
|
||||
await _notificationService.cancelNotification();
|
||||
await BackgroundStreamingHandler.instance.stopBackgroundExecution(const [
|
||||
_voiceCallStreamId,
|
||||
]);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
@@ -331,6 +341,10 @@ class VoiceCallService {
|
||||
await _voiceInput.stopListening();
|
||||
await _tts.stop();
|
||||
|
||||
await BackgroundStreamingHandler.instance.stopBackgroundExecution(const [
|
||||
_voiceCallStreamId,
|
||||
]);
|
||||
|
||||
// Cancel notification
|
||||
await _notificationService.cancelNotification();
|
||||
|
||||
@@ -435,6 +449,10 @@ class VoiceCallService {
|
||||
// Ensure wake lock is disabled on dispose
|
||||
await WakelockPlus.disable();
|
||||
|
||||
await BackgroundStreamingHandler.instance.stopBackgroundExecution(const [
|
||||
_voiceCallStreamId,
|
||||
]);
|
||||
|
||||
await _stateController.close();
|
||||
await _transcriptController.close();
|
||||
await _responseController.close();
|
||||
|
||||
Reference in New Issue
Block a user