1

I have read both the posts on this:

Should have subtitle controller already set Mediaplayer error Android

This one talks about ignoring & suppressing the error. Does NOT solve my problem.

And this one:

MediaPlayer : Should have subtitle controller already set: KitKat

Has no valid answer.

The problem I am having is this: Audio used to play, but we had to change our framework (we removed CrossWalk) and now audio no longer plays. Thing is, removing CrossWalk had nothing to do with my mediaplayer code.

So the error I get occurs twice in succession. In my code I do this:

        _activeMediaPlayer.prepare();
        _activeMediaPlayer.start();

When either of those 2 lines are called it throws the error:

E/MediaPlayer: Should have subtitle controller already set

Setting the stream type does not affect this in any way. Also, it doesnt throw an exception but it also does NOT fire the OnCompletionListener

      _activeMediaPlayer.setOnCompletionListener
        (
            new MediaPlayer.OnCompletionListener()
            {
                @Override
                public void onCompletion(MediaPlayer mp)
                {
                    _activeMediaPlayer = null;
                    Log.d("AudioPlayer", "Completed audio playing");
                }
            }
        );

Do you have any idea why the audio might not play? (100% can confirm phone audio is working and volume is on max). This code used to work!

Update Here is my entire audio playing class. This used to work perfectly. The audio files it plays have not changed paths or formats. Its literally just stopped working with no errors thrown.

public class AudioPlayer
{
    //region Variables

    private static final String AUDIO_TYPE_DOWNLOADED   = "downloaded";
    private static final String AUDIO_TYPE_BUNDLED      = "bundled";
    private static final String AUDIO_BUNDLED_PATH      = "www/audio/";
    private static final String AUDIO_DOWNLOADED_PATH   = "file:///data/data/co.app.app/Documents/";

    private static AudioManager _audioManager;

    private static AudioPlayer _singleton;

    private static Activity _activity;

    private static ArrayList<MediaPlayer> _audioList;

    private static MediaPlayer _activeMediaPlayer = null;
    //endregion

    //region Initialization

    /*
     * Must be called before using Singleton. Will initialize with activity.
     */
    public static void initialize(Activity activity)
    {
        _activity = activity;

        _singleton = new AudioPlayer();

        _audioList = new ArrayList<>();

        _audioManager = SINGLETON().createAudioManager();
    }

    /**
     * Access this to play audio.
     */
    public static AudioPlayer SINGLETON()
    {
        if (_singleton == null)
        {
            System.out.println("Error audio helper not initialized, call Initialize first");
            return null;
        }

        return _singleton;
    }

    /**
     * Creates an audio manager.
     */
    private AudioManager createAudioManager()
    {
        final AudioManager audioManager =
            (AudioManager) _activity.getBaseContext().getSystemService(Context.AUDIO_SERVICE);
        return audioManager;
    }
    //endregion

    //region Audio Focus

    /**
     * Listener for audio focus changes.
     */
    private AudioManager.OnAudioFocusChangeListener createAudioFocusChangeListener()
    {
        return new AudioManager.OnAudioFocusChangeListener()
        {
            public void onAudioFocusChange(int focusChange)
            {
                if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)
                {
                    //TODO leave in case features are desired here
                } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN)
                {
                    //TODO leave in case features are desired here
                }
            }
        };
    }

    /*
     * Sets audio focus to duck others.
     */
    private int requestAudioFocus(AudioManager audioManager,
                                  AudioManager.OnAudioFocusChangeListener audioFocusListener)
    {
        // Use the music stream and request permanent focus.
        return audioManager.requestAudioFocus
        (
                audioFocusListener,
                AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
        );
    }
    //endregion

    //region Playing & Queueing Audio

    /*
     * Enqueue audio for play.
     */
    private static void enqueueAudio(String path, String audioType)
    {
        MediaPlayer mediaPlayer = new MediaPlayer();

        if (audioType.equals(AUDIO_TYPE_BUNDLED))
        {
            try
            {
                AssetFileDescriptor afd =
                    _activity.getAssets().openFd(AUDIO_BUNDLED_PATH + path + ".m4a");
                mediaPlayer.setDataSource
                (
                    afd.getFileDescriptor(),
                    afd.getStartOffset(),
                    afd.getLength()
                );
            } catch (IOException e)
            {
                System.out.println("Error bundled file not found ");
                e.printStackTrace();
                return;
            }
        } else
        {
            Uri uri = Uri.parse(AUDIO_DOWNLOADED_PATH + path + ".m4a");
            try
            {
                mediaPlayer.setDataSource(_activity,uri);
            } catch (IOException e)
            {
                e.printStackTrace();
                System.out.println("Could not find audio at " + path);
                return;
            }
        }

        _audioList.add(mediaPlayer);
    }

    /**
     * Enqueues all audio then plays it.
     * Example format: String json = "{\"audio\":[{\"path\":\"a\",\"type\":\"bundled\"},
     * {\"path\":\"444-1438314705229\",\"type\":\"downloaded\"}]}";
     */
    public static void playAudio(String json)
    {
        try
        {
            JSONObject rootJson = new JSONObject(json);
            JSONArray arrayJson = rootJson.getJSONArray("audio");

            for (int i = 0; i < arrayJson.length(); i++)
            {
                JSONObject audioJson = (JSONObject) arrayJson.get(i);
                enqueueAudio(audioJson.getString("path"), audioJson.getString("type"));
            }
        } catch (Exception e)
        {
            System.err.println("JSON parsing error " + e.getMessage());

            if (Bridge.audioCallback != null)
            {
                Bridge.audioCallback.error(e.getMessage());
            }
        }

        playQueuedAudio();
    }

    /**
     * Plays the top most queued audio (is called by the onComplete listener)
     */
    private static void playQueuedAudio()
    {
        final AudioManager.OnAudioFocusChangeListener audioFocusListener =
            SINGLETON().createAudioFocusChangeListener();

        int result = SINGLETON().requestAudioFocus(_audioManager, audioFocusListener);

        if (_audioList.isEmpty())
        {
            _audioManager.abandonAudioFocus(audioFocusListener);

            if (Bridge.audioCallback != null)
            {
                Bridge.audioCallback.success();
            }

            return;
        }

        if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
        {
            System.err.println("Could not gain audio focus, not playing audio");
            return;
        }

        try
        {
            _activeMediaPlayer = _audioList.get(0);

            _audioList.remove(0);

            _activeMediaPlayer.prepare();
            _activeMediaPlayer.start();
            _activeMediaPlayer.setOnCompletionListener
            (
                new MediaPlayer.OnCompletionListener()
                {
                    @Override
                    public void onCompletion(MediaPlayer mp)
                    {
                        _activeMediaPlayer = null;
                        playQueuedAudio();
                    }
                }
            );
        } catch (IOException e)
        {
            String message = "Unable to open media file: " + e.getMessage();
            System.err.println(message);

            if(Bridge.audioCallback != null)
            {
                Bridge.audioCallback.error(message);
            }
        }

    }

    /**
     * Stops audio.
     */
    public static void stopAudio(CallbackContext callbackContext)
    {
        if (_activeMediaPlayer != null && _activeMediaPlayer.isPlaying())
        {
            _activeMediaPlayer.stop();
        }

        _audioList.clear();

        _activeMediaPlayer = null;

        callbackContext.success();
    }
    //endregion
}

One Final Note

As a test I created a test activity and just wrote this inside it as soon as the app installed:

MediaPlayer mediaPlayer = MediaPlayer.create(context,R.raw.test);
mediaPlayer.start(); 

This also doesnt work. Something is afoot here...

Community
  • 1
  • 1
Aggressor
  • 13,323
  • 24
  • 103
  • 182
  • I would say there's a very good chance the 'subtitle controller..' message is completely unrelated to whatever is causing your audio not to play. I see that message constantly with a media player object that is playing music. – Tim Malseed Dec 09 '15 at 00:49
  • Also, what's your media player data source? Are you streaming audio? if so, do you have the internet permission? Set an onPreparedListener. Is that getting called? – Tim Malseed Dec 09 '15 at 00:51
  • Hmm if thats the case shouldnt there be some sort of error logging when the audio doesnt play? :( – Aggressor Dec 09 '15 at 17:21
  • My data source are .m4a files (which used to work). All permissions are there. I will check the onPreparedListener now – Aggressor Dec 09 '15 at 17:53
  • The OnPreparedListener is firing. – Aggressor Dec 09 '15 at 18:16
  • You need to provide some more code, there's not enough information to help you. Please show how you set the media player datasource. Also, do other filetypes work? – Tim Malseed Dec 09 '15 at 22:08
  • Ive added all my code, my resources are stored inside the `assets` folder. – Aggressor Dec 09 '15 at 22:40

2 Answers2

1

After much research I have concluded that the codec used to encode the audio file was corrupt. m4a works for Android but it seems some codecs don't work properly (the header portion can get messed up as far as I can tell).

As such I converted all to mp3 and it works fine now.

Aggressor
  • 13,323
  • 24
  • 103
  • 182
0

This happened to me when running my audio app in the Emulator(Nexus S API 22).

I made a cool boot and the error was gone. No more crashes.

John T
  • 814
  • 10
  • 17