iosflutterfileaudioflutter-audioplayers

AudioPlayers does not work on iOS | Flutter plugin


I am creating a Flutter plugin. Currently, the code:

  1. Synthesises an String into an audio file
  2. Gets the path to the file
  3. Plays the audio file using audioplayers

When I run the application in Android, it perfectly works. Nevertheless, when I run it on iOS, it does not (assuming relates permissions/restrictions)

await flutterTts
        .synthesizeToFile(
            "This is my first audio synthesizer in Flutter", audioFileName)
        .then((success) => {
              if (success == 1)
                {
                  print('Successfully synthesized!!'),

                  // Gets the path to the generated file depending on the platform
                  pathFile =
                      Platform.isAndroid ? pathToFileAndroid : pathToFileIos,
                  pathFile
                      .then((pathToAudioFile) => {
                            print('Path to file: ' + pathToAudioFile),
                            // Speakers/earpiece
                            // int result = await player.earpieceOrSpeakersToggle();
                            // Sets the path to the file
                            audioPlayer.setUrl(pathToAudioFile),
                            audioPlayer.setVolume(1.0),
                            // Gets the duration of the audio file to be reproduced
                            // Plays the audio file
                            playLocal(audioPlayer, pathToAudioFile),
                          }) // pathFile
                      .catchError((e) {
                    print('Error: Unable to get the path to the audio file');
                  }),
                }, // success
            }) //synthesizeToFile
        .catchError((e) {
      print('Error during the synthesisation: $e');
    });
  }




/// Gets the path to the file to be accessed (iOS)
  static Future<String> get pathToFileIos async {
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path;
    print('appDocPath: $appDocPath');
    return '$appDocPath/$audioFileName';
  }

I implemented audioPlayer.onDurationChanged.listen to confirm that the path to the file is the correct one (it actually gets the duration of the file). Nevertheless, the file is not played.

I am using a simulator to test the application, and this is the path where the file is stored

/localPaty/Devices/deviceID/data/Containers/Data/Application/appID/Documents/temp_audio_cue.caf

I read different questions regarding this topic, but I did not find a solution for my case

I have tried:

Editing Transport security as the documentation recommends

   <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict> 

Using AudioCache (question)

Anyone has any other suggestion? Do I need to move the file to my local assets and use AudioCache to reproduce the file?

Update

I have also tried to add the flag isLocal.

  playLocal() async {
    int result = await audioPlayer.play(localPath, isLocal: true);
  }

According to the documentation is is needed cause

The isLocal flag is required only because iOS and macOS make a difference about it

It returns 1, so I guess that it means success, but the sound is still not triggered. Could be the simulator failing?

"iOS => call startHeadlessService, playerId ID"
"iOS => call setUrl, playerId ID"
"iOS => call setVolume, playerId ID"
"iOS => call play, playerId ID"
2021-02-03 11:59:33.149925+0100 Runner[61496:850044] flutter: Played successfully?: 1

I have also tested to call playLocal() with a wrong path. It keeps returning 1 but after it it displays the following error:

FigFileForkOpenMainByCFURL signalled err=2 (errno) (open failed)

Nevertheless, the error is not triggered with calling the method with the correct localPath so I assume it should be playing it correctly.

Note

If instead of calling playLocal(), I call flutter_tts.speak('test'), it works. Therefore, the error should probably be related to audioplayers.

The versions that I am using are flutter_tts ^2.1.0 and audioplayers: ^0.17.3


Solution

  • final AudioContext audioContext = AudioContext(
        iOS: AudioContextIOS(
          defaultToSpeaker: true,
          category: AVAudioSessionCategory.ambient,
          options: [
            AVAudioSessionOptions.defaultToSpeaker,
            AVAudioSessionOptions.mixWithOthers,
          ],
        ),
        android: AudioContextAndroid(
          isSpeakerphoneOn: true,
          stayAwake: true,
          contentType: AndroidContentType.sonification,
          usageType: AndroidUsageType.assistanceSonification,
          audioFocus: AndroidAudioFocus.none,
        ),
      );
      AudioPlayer.global.setGlobalAudioContext(audioContext);
    

    Add this in you main.dart file before this runApp(App());