MediaPlayer : Should have subtitle controller already set: KitKat - android

I am having an odd issue where my audio file sometimes plays and sometimes does not play. The catch is that when it decides to not play, the DDMS gives me an:
E/MediaPlayer﹕ Should have subtitle controller already set
Because this is one-to-one with the music not playing, I have determined that this is probably the issue...
If the music is not playing and I hit the volume button it begins to play.
If I wait about 30 seconds of no-play, it begins to start again (not looping).
Whats going on here? I am on KitKat using
player = new MediaPlayer();
AssetFileDescriptor afd = null;
try {
afd = getAssets().openFd("Theme.mp3");
} catch (IOException e) {
e.printStackTrace();
}
try {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IOException e) {
e.printStackTrace();
}
try {
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
player.setLooping(true); //restart playback end reached
//player.setVolume(1, 1); //Set left and right volumes. Range is from 0.0 to 1.0
player.start(); //start play back

Looking at a previous discussion on StackOverflow, and the referenced Android commit where this was introduced, the code above might not completely initialize the MediaPlayer object.
The KitKat example code for media playback suggests that you should call:
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
immediately after you construct the MediaPlayer, and before you call its setDataSource method.

I had the same issue and I fixed it by adding the following right after instantiating MediaPlayer.
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (mp == mediaPlayer) {
mediaPlayer.start();
}
}
});
Previously I was implementing MediaPlayer.OnPreparedListener and overriding onPrepared() but it didn't work.
I hope this helps!

This should fix your problem (did for me): Replace the line that says "player.start()" following the rest of your code with an async callback like so:
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
This error is just a Log.e, not a real error. It shouldn't cause your player to not play, I'm guessing it's just because the player hadn't finished preparing when you try to call start().
E/MediaPlayer﹕ Should have subtitle controller already set

Its been a long time since I was working on this app. Here is what I ended up doing to get this to work. (Tested on KitKat and Lollipop). I think switching from MediaPlayer to APMediaPlayer was part of the trick.
#Override
public void onDestroy() {
if(player != null) {
player.release();
player = null;
}
super.onDestroy();
}
#Override
public void onStart() {
super.onStart();
if(player != null) {
player.start();
}
else {
player = new APMediaPlayer(this); //create new APMediaPlayer
player.setMediaFile("Theme.mp3"); //set the file (files are in data folder)
player.start(); //start play back
player.setLooping(true); //restart playback end reached
player.setVolume(1, 1); //Set left and right volumes. Range is from 0.0 to 1.0
}
}
#Override
public void onResume() {
super.onResume();
if(player != null) {
player.start();
}
}

set in manifest file may help you
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Related

Audio file in application doesn't stop on click, it starts playing again

So I put an audio file in my application and it's supposted play when I touch the button and stop when I touch it again.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button one = (Button) findViewById(R.id.buttonId);
final MediaPlayer mp = new MediaPlayer();
one.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
if(mp.isPlaying())
{
mp.stop();
}
try {
mp.reset();
AssetFileDescriptor afd;
afd = getAssets().openFd("mosq.mp3");
mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
mp.prepare();
mp.setLooping(true);
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
here is my code, this part:
if(mp.isPlaying())
{
mp.stop();
}
didn't work for some reason.
Make sure you put a return statement below mp.stop().
From what I can understand the sound does stop but then it starts again because the next part of the code still gets executed
As George D correctly pointed out, you start the media playing unconditionally, even if you just stopped it. You could use his solution or do something like:
if(mp.isPlaying())
{
mp.stop();
}
else {
try {
mp.reset();
AssetFileDescriptor afd;
afd = getAssets().openFd("mosq.mp3");
mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
mp.prepare();
mp.setLooping(true);
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
This has several other potential bugs in it:
* I'm not sure if this is what you intended but the player won't ever pause, just stop and restart from the beginning. If you try to resume or play again it'll completely reload the audio file every time. At a minimum this is a waste of resources, plus it's likely not the expected behavior from a UI perspective.
* You don't want to define the MediaPlayer object as a local variable within the OnCreate method. The only reason this works at all is you have a memory leak (you never unsubscribe your event handler for the click); if you didn't have the memory leak the object would become eligible for garbage collection as soon as you completed the onCreate method and, as far as the framework was concerned, it would no longer exist.

android -how to program button next for playing new media

I already initialise a media by setDataSource and doing function prépare() start(). I want starting new média by click on button next, but what doing? Stop already media and do setDataSource and prépare()
Start() for next media?
Just reset mediaplayer before playing next song,then set new datasource and start it
public void startPlaying(String audioURL)
{
mediaPlayer.reset();
try
{
if(audioURL != null)
{
mediaPlayer.setDataSource(audioURL);
}
mediaPlayer.prepare();
mediaPlayer.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
You can set a callback when the playback of your MediaPlayer has finished. There you can set a new Datasource.

android play sound from sd-card

I need to play sound from sd card. I have method that must do this but it's doesn't work.
When I use this method:
public class AudioPlayService extends Service
{
MediaPlayer mMediaPlayer;
..............
public void soundplay(String adr)
{
mMediaPlayer = new MediaPlayer();
try
{
if (mMediaPlayer.isPlaying())
{
mMediaPlayer.reset();
}
mMediaPlayer.setDataSource(adr);
mMediaPlayer.prepare();
} catch (IOException e)
{
}
mMediaPlayer.start();
mMediaPlayer.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
mp.release();
mp = null;
}
});
}
Where String adr - it's absolute path to file on sd.
Then I call it:
AudioPlayService s = new AudioPlayService();
s.soundplay(iA.getSdDir() + "Files/Numbers/0.mp3");
and I get an err's:
12-09 13:04:13.829: E/MediaPlayer(16997): error (1, -2147483648)
12-09 13:04:13.829: E/MediaPlayer(16997): start called in state 0
12-09 13:04:13.829: E/MediaPlayer(16997): error (-38, 0)
12-09 13:04:13.839: E/MediaPlayer(16997): Error (-38,0)
I myself tried your code:
Mine worked fine when i put just "sdcard/1.mp3"
You ensure that the path is right or not
s.soundplay(iA.getSdDir() + "Files/Numbers/0.mp3");
Note:
If you are trying to make your method soundplay so as to stop previous audio and play the new audio file, then better would be not to perfom this inside that method
mMediaPlayer = new MediaPlayer();
Place this in constructor.
Otherwise each time you invoke s.soundplay(path) you will hear previous audio plus the new audio. ie,Previous one will not be stopped
player.start() put within try,catch block. Because if player not prepare your song ,still you are calling start method.start method is only called after playback is ready,
means prepare is success.Another thing is that you have to release the media player when your player is no longer.Otherwise there is so many player objects are running in back ground.
For some reason, your setDataSource() or Prepare() is failing. So after the exception, start()is giving the error, since the player is not in Prepared state. Add print statements in the catch block to know what is the exception. And move start() into the try catch block.
mMediaPlayer = new MediaPlayer();
try
{
if (mMediaPlayer.isPlaying())
{
mMediaPlayer.reset();
}
mMediaPlayer.setDataSource(adr);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IOException e)
{
e.printStackTrace();
}

Create() fails in MediaPlayer - android

I am trying to play a few music (wav format) files based on button clicks. I am unable to get MediaPlayer to work properly. Every time I try to instantiate an object of MediaPlayer class, it fails on create(). Before I post the code, here is a run-through of what I am doing:
1. A layout file that contains 2 buttons.
2. Those buttons are read and onClickListeners defined for them.
3. Depending on the button clicked, a function called playAudioFile(View) called which creates the MediaPlayer instance and plays the file. The code for playAudioFile(View) is as follows:
public void playAudioFile(View v) {
/*Steps:
* 1. Take in id of the button.
* 2. Using id, identify what file needs to be played.
* 3. Play file.
*/
String path_to_file = null; //this is the path to the file.
if(b01.getId() == ((Button)v).getId()) {
Log.v(this.toString(), "Button 01 pressed.");
path_to_file = "/sdcard/audio/temp1.wav";
} else if(b02.getId() == ((Button)v).getId()) {
Log.v(this.toString(), "Button02 pressed.");
path_to_file = "/sdcard/audio/temp2.wav";
}
path_to_file = "file://" + path_to_file;
Uri streamUri = Uri.parse(path_to_file);
Log.v(this.toString(), "Path of file = " + path_to_file);
MediaPlayer mp = MediaPlayer.create(this, streamUri);
if(mp == null) {
Log.v(this.toString(), "Create() on MediaPlayer failed.");
}
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
try {
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
Log.v(this.toString(), "Illegal state exception thrown in start.");
}
}
});
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
}
I have gone through a lot of posts here on stackoverflow that detail solutions to the above problem. I am encountering this problem after having incorporated all the suggestions made therein. Any help is most welcome.
Thanks,
Sriram
I dont understand why you are trying to do
MediaPlayer mp = MediaPlayer.create(this, streamUri);
This is my implementation of my Player, Hope this will help you in some way:
MediaPlayer mp = new MediaPlayer();
setContentView(R.layout.player);
Intent intent = getIntent();
String path = "";
System.out.println("My Scheme : "+intent.getData().toString().substring(8));
if (intent.getData().getScheme().equals("video")) {
path = intent.getData().toString().substring(8);
System.out.println("Path : "+path);
if(path.endsWith(".mp3")) {
setContentView(R.layout.musicplayer);
setContentView(R.layout.controls);
Log.e("MusicPlayer", "Playing: " + path);
try {
Notification notification = new Notification(
R.drawable.playbackstart, path, System.currentTimeMillis());
nm.notify(NOTIFY_ID, notification);
mp.reset();
mp.setDataSource(path);
mp.prepare();
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
System.out.println("Hi i am at the End");
}
});
}catch {expression}
If I'm not wrong, you can't use onPrepare because mp.prepare() is called inside MediaPlayer.create(). The simpliest code can be something like this:
MediaPlayer mp = MediaPlayer.create(this, streamUri);
mp.start();
If you want something more elaborated, you can try this:
MediaPlayer mp = MediaPlayer.create(this, streamUri);
if(mp == null) {
Log.v(this.toString(), "Create() on MediaPlayer failed.");
} else {
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//here you should call the methods to release memory
mp.stop();
mp.release();
}
});
mp.start();
}
Tell me if it helped you.
PD: Is better if you use a device for testing rather than a simulator. Some classes don't work properly there (MediaPlayer can't reproduce video in simulators) and I don't remember if it supports audio.
As far as I understand your problem: You are calling the MediaPlayer.create(...) method, and it returns null, meaning the creation of a MediaPlayer instance failed. According to the accepted answer of this post MediaPlayer.create() always returns null it is due to a corrupted audio file.
I also have an issue, where the sound gets played but on rare occasions the create() method also returns null. I use sounds in a turn based game, after each turn a sound is played. I always call the create method, start the player and release it when it's done. That happens every turn and like once in 300 turns the create method returns null... So in my case it must be something else. In yours it could probably have something to do with the corruption of the mp3 file.

Strange behaviour with mediaplayer and seekTo

I'm implementing a custom video player because I need custom video controls. I have an app with only one activity, which on startup shall start playing a video right away.
Now, the problem I have is:
I don't want the video to start from the beginning, but from a later position. Therefore I do a seekTo(16867). Since seekTo is asynchronous, I place the start call of the mediaplayer (player.start()) in the onSeekComplete of the onSeekCompleteListener.
The strange behaviour I experience though is that I can see/hear the video playing from the beginning for a few millisecs before it actually plays from/jumps to the position I seeked to.
But - on the other hand - the Log output I call before the player.start returns the correct position 16867, where I seeked to.
Below is the relevant code section, the complete class is at http://pastebin.com/jqAAFsuX
(I'm on Nexus One / 2.2 StageFright)
private void playVideo(String url) {
try {
btnVideoPause.setEnabled(false);
if (player==null) {
player=new MediaPlayer();
player.setScreenOnWhilePlaying(true);
}
else {
player.stop();
player.reset();
}
url = "/sdcard/myapp/main/videos/main.mp4"; // <--- just for test purposes hardcoded here now
player.setDataSource(url);
player.setDisplay(holder);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnCompletionListener(this);
player.setOnPreparedListener(this);
player.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
public void onSeekComplete(MediaPlayer mediaPlayer) {
Log.d("APP", "current pos... "+ player.getCurrentPosition() );
player.start(); // <------------------ start video on seek completed
player.setOnSeekCompleteListener(null);
}
});
player.prepareAsync();
}
catch (Throwable t) {
Log.e(TAG, "Exception in btnVideoPause prep", t);
}
}
public void onPrepared(MediaPlayer mediaplayer) {
width=player.getVideoWidth();
height=player.getVideoHeight();
if (width!=0 && height!=0) {
holder.setFixedSize(width, height);
progressBar.setProgress(0);
progressBar.setMax(player.getDuration());
player.seekTo(16867); // <------------------ seeking to position
}
btnVideoPause.setEnabled(true);
}
Since I also haven't recieved any reply from the Android developer list and found similar issues on the web, I conclude it's a bug. I filed a bug report at http://code.google.com/p/android/issues/detail?id=9135

Categories

Resources