ios objective-c avspeechsynthesizer background-mode avspeechutterance

ios - Reproducción de sonido en didReceiveRemoteNotification, mientras que en segundo plano, utiliza la función de texto a voz



objective-c avspeechsynthesizer (2)

Como no puedo reproducir el error que está describiendo, permítame ofrecerle algunos consejos y algunos códigos.

  • ¿Está compilando / probando / corriendo contra el último SDK? Ha habido cambios significativos en el mecanismo de notificación en iOS X
  • Debo asumir que la invocación a didReceiveRemoteNotification debe ocurrir en respuesta a una acción del usuario de dicha notificación, como por ejemplo, al tocar el mensaje de notificación.
  • No es necesario configurar ninguno de los modos de fondo en los que la aplicación descarga contenido en respuesta a las notificaciones push .

Si todas las afirmaciones anteriores son verdaderas, la respuesta actual se centrará en lo que sucede cuando llega una notificación.

  1. Dispositivo recibe notificación
  2. El usuario toca el mensaje
  3. Lanzamientos de aplicaciones
  4. didReceiveRemoteNotification se invoca

En el paso 4, textToSpeechWithMessage funciona como se esperaba:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { textToSpeechWithMessage(message: "Speak up", "en-US") }

Para simplificar, estoy usando OneSignal para conectar las notificaciones:

import OneSignal ... _ = OneSignal.init(launchOptions: launchOptions, appId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") // or _ = OneSignal.init(launchOptions: launchOptions, appId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") { (s:String?, t:[AnyHashable : Any]?, u:Bool) in self.textToSpeechWithMessage(message: "OneDignal", "en-US") }

textToSpeechWithMessage está casi intacto, aquí está en Swift 3 para completar:

import AVFoundation ... let synthesizer = AVSpeechSynthesizer() func textToSpeechWithMessage(message:String, _ languageCode:String) { let audioSession = AVAudioSession.sharedInstance() print("Activating audio session") do { try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: [AVAudioSessionCategoryOptions.defaultToSpeaker, AVAudioSessionCategoryOptions.mixWithOthers] ) try audioSession.setActive(true) let utterance = AVSpeechUtterance(string:message) utterance.rate = 0.5 utterance.volume = 0.8 utterance.voice = AVSpeechSynthesisVoice(language: languageCode) self.synthesizer.speak(utterance) } catch { print("Unable to set audio session category: %@", error); } }

Lo que estoy intentando actualmente es reproducir un mensaje cuando la aplicación recibe una notificación remota mientras está en segundo plano (o es probable que se haya despertado de un estado suspendido).

El sonido no se reproduce en absoluto después de que la aplicación se haya activado desde un modo suspendido.

Cuando la aplicación está en primer plano, se reproduce un sonido inmediatamente después de didReceiveRemoteNotification: método didReceiveRemoteNotification:

¿Cuál sería una forma adecuada de reproducir los sonidos inmediatamente cuando se didReceiveRemoteNotification: método didReceiveRemoteNotification: mientras la aplicación se despierta de un modo suspendido?

Aquí está el código (clase de administrador de voz):

-(void)textToSpeechWithMessage:(NSString*)message andLanguageCode:(NSString*)languageCode{ AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; DLog(@"Activating audio session"); if (![audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers error:&error]) { DLog(@"Unable to set audio session category: %@", error); } BOOL result = [audioSession setActive:YES error:&error]; if (!result) { DLog(@"Error activating audio session: %@", error); }else{ AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:message]; [utterance setRate:0.5f]; [utterance setVolume:0.8f]; utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:languageCode]; [self.synthesizer speakUtterance:utterance]; }

}

-(void)textToSpeechWithMessage:(NSString*)message{ [self textToSpeechWithMessage:message andLanguageCode:[[NSLocale preferredLanguages] objectAtIndex:0]]; }

Y más adelante en AppDelegate :

[[MCSpeechManager sharedInstance] textToSpeechWithMessage:messageText];

He habilitado la opción Audio, AirPlay e Imagen en imagen en la sección Capacidades -> Modos de fondo.

EDITAR:

¿Tal vez debería comenzar una tarea en segundo plano y ejecutar el controlador de caducidad si es necesario? Supongo que podría funcionar, pero también me gustaría escuchar la forma común de resolver este tipo de situaciones.

También con este código recibo el siguiente error cuando recibo una notificación en segundo plano:

Error al activar la sesión de audio: Dominio de error = NSOSStatusErrorDomain Code = 561015905 "(null)"

El código 561015905 se aplica a:

AVAudioSessionErrorCodeCannotStartPlaying = ''! Pla'', / * 0x21706C61, 561015905

Y se describe como:

Este tipo de error puede ocurrir si la lista de propiedades de información de la aplicación no permite el uso de audio, o si la aplicación está en segundo plano y utiliza una categoría que no permite audio de fondo.

pero estoy recibiendo el mismo error con otras categorías ( AVAudioSessionCategoryAmbient y AVAudioSessionCategorySoloAmbient )


Por favor implementar

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

método. Obtendrás callback en segundo plano para reproducir audio.