Search code examples
androidxamarin.formsandroid-mediaplayermedia-player

android mediaplayer SetDataSource(AssetFileDescriptor) does not work < API 24


I am using Xamarin.Forms where, in my android project, I have a custom AudioManager class to play audio files.

I have code that plays an embedded audiofile from the assets directory with the Android.Media.MediaPlayer class.

This code works fine on devices with API24 and above. But it generates an exception on the mediaplayer.SetDataSource(assetFileDescriptor) for devices with API 23 and lower.

The exception reads "Java.Lang.NoSuchMethodError: no non-static method "Landroid/media/MediaPlayer;.setDataSource(Landroid/content/res/AssetFileDescriptor;)"

Is this a known problem? and if so, how do you work around this.

my code:

public void PlayEmbeddedSound(string soundFileName) { if (_mediaPlayer != null && _mediaPlayer.IsPlaying) { _mediaPlayer?.Stop(); } _mediaPlayer?.Reset(); _mediaPlayer?.Release(); _mediaPlayer = new MediaPlayer(); if (Android.OS.Build.VERSION.SdkInt > Android.OS.BuildVersionCodes.Lollipop) { //not supported @ API16 var attributes = new AudioAttributes.Builder() .SetUsage(AudioUsageKind.VoiceCommunication) .SetContentType(AudioContentType.Speech) .SetFlags(AudioFlags.AudibilityEnforced) .Build(); _mediaPlayer.SetAudioAttributes(attributes); } _mediaPlayer.SetVolume(1F, 1F); var assetsSoundsDir = "Sounds"; var soundPath = System.IO.Path.Combine(assetsSoundsDir,soundFileName); var assetFileDescriptor = Android.App.Application.Context.Assets.OpenFd(soundPath); _mediaPlayer.Prepare(); _mediaPlayer.Completion -= _mediaPlayer_Completion; _mediaPlayer.Completion += _mediaPlayer_Completion; _mediaPlayer.Start(); }


Solution

  • hmm apparently the method signature

    _mediaPlayer.SetDataSource(assetFileDescriptor); 
    

    was introduced in a later API, (I could not find in the documentation that this method signature is not valid in lower API versions)

    but the method signature

    _mediaPlayer.SetDataSource(assetFileDescriptor.FileDescriptor, assetFileDescriptor.StartOffset, assetFileDescriptor.Length);
    

    does seem to work < API24