Why does MediaPlayer.setLooping() cause an error when using VideoView? - java

We are trying to use a VideoView to play a video in an Android Activiy.
I've read the MediaPlayer documentation and studied its state diagram.
We get a Media Player error if we call this method:
MediaPlayer.setLooping()
from this listener method:
MediaPlayer.OnPreparedListener.onPrepared()
The error message from LogCat:
error (-38, 0)
Note:
We have tested on two physical devices and this only happens on our Motorola Xoom.
If I comment out this line: mp.setLooping(false); everything works fine on the Xoom.
(see code below)
According to the documentation, setLooping() can be called from the following Media Player states:
Idle
Initialized
Stopped
Prepared
Started
Paused
PlaybackCompleted
Although the documentation also includes this seemingly contradictory statement:
It is a programming error to invoke methods such as getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioStreamType(int), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int), prepare() or prepareAsync() in the Idle state...
Question 1:
Why can't we call setLooping() from onPrepared()?
Question 2:
Shouldn't the VideoView be handling the preparation of the underlying MediaPlayer?
Question 3:
Shouldn't the MediaPlayer be in its prepared state when onPrepared() is invoked?
Question 4:
How do I resolve the statements in the documentation that seem to contradict each other?
What really confuses me:
The quote above says none of these methods should be called when the MediaPlayer is in its idle state:
getCurrentPosition()
getDuration()
getVideoHeight()
getVideoWidth()
setAudioStreamType(int)
setLooping(boolean)
setVolume(float
float)
pause()
start()
stop()
seekTo(int)
prepare()
prepareAsync()
This statement (along with our error message) makes me think our error occurs because the MediaPlayer has not been successfully prepared.
But, for some reason there is no problem calling setAudioStreamType().
Question 5:
Why is there a problem with setLooping() but not with setAudioStreamType()?
Both methods are in the list of forbidden methods above.
(That said, I would've thought both are valid in the onPrepared() method...)
What am I missing?
Is there a bug with the Motorola Xoom?
I'd be happy to just get an answer to question 1, but I'm really perplexed by all of this.
I'll admit I'm pretty new to Android development...
Our Xoom is running Ice Cream Sandwich 4.0.4.
Here's some sample code:
class VideoActivity {
VideoView mVidView;
#Override
protected void onCreate(Bundle b) {
mVidView = new VideoView(this);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(mWidth, mHeight);
mVidView.setLayoutParams(params);
mVidView.setVideoURI(mUri);
mVidView.setZOrderOnTop(true);
mMediaController = new MediaController(this, true);
mMediaController.setAnchorView(null);
mVidView.setMediaController(mMediaController);
mVidView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
.
.
.
}
});
mVidView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
.
.
.
}
});
mVidView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mDialog.dismiss();
mMediaPlayer = mp;
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setLooping(false);
mp.setScreenOnWhilePlaying(true);
mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
public void onSeekComplete(MediaPlayer mp) {
mp.start();
}
});
if (mTimecode > 0) {
mp.seekTo(mTimecode * ONE_SEC);
} else {
mp.start();
}
mMediaController.show(0);
}
});
LinearLayout ll = (LinearLayout) this.findViewById(R.id.parentpopup);
ll.addView(mVidView);
}
}

Related

I can't understand this MediaPlayer error: MediaPlayerNative: stop called in state 0, mPlayer(0x7efba92280)

When the app starts everything is fine. But after some time it stops playing sound. but the app does not crash. I didn't understand what wrong with it.
Here my MediaPlayer code:
holder.btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer!=null){
mediaPlayer.stop();
}
mediaPlayer =MediaPlayer.create(mContext,mChineseLanguages.get(position).getSound());
mediaPlayer.start();
}
});
In logcats the following error is being displayed
MediaPlayerNative: stop called in state 0,
mPlayer(0x7efba92280) MediaPlayerNative: error (-38, 0)
You need to implement mediaPlayer's onPreparedListener and start the player inside it. The abover error is producing because you are starting the player before it reaches the onPrepared state.
For example-
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.prepareAsync();
public void onPrepared(MediaPlayer player) {
player.start();
}

Media Player doesn't play for the second time

I use same button for play and pause.It can handle play and pause smoothly.But after the music file end, it can not play it again.When I press it restart the application.I use mp.reset(); mp.release();.It doesn't help me in the case
Java Code:
final MediaPlayer mp1;
mp1 = MediaPlayer.create(convertView.getContext().getApplicationContext(), convertView.getResources().getIdentifier(audiopath, "raw", convertView.getContext().getPackageName()));
mHolder.play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mp1.isPlaying()) {
mp1.pause();
mHolder.play.setImageResource(R.drawable.plays);
} else {
mp1.start();
mHolder.play.setImageResource(R.drawable.pause);
mp1.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.reset();
mp.release();
mHolder.play.setImageResource(R.drawable.plays);
}
});
}
}
});
LogCat:
java.lang.IllegalStateException
at android.media.MediaPlayer.isPlaying(Native Method)
at com.example.package.adapter.AdapterN$3.onClick(AdapterN.java:223)
img ref
Problem
When you call release() of a MediaPlayer, it deallocates all its resources allocated with MediaPlayer.create() previously, hence no longer being accessible. This produces,
java.lang.IllegalStateException
at android.media.MediaPlayer.isPlaying(Native Method)
at com.example.package.adapter.AdapterN$3.onClick(AdapterN.java:223)
Solution
You should remove,
mp.release()
However, you can still use release() but in that case you have to again create MediaPlayer instance using,
mp1 = MediaPlayer.create(convertView.getContext().getApplicationContext(), convertView.getResources().getIdentifier(audiopath, "raw", convertView.getContext().getPackageName()));
in proper place (i.e. before accessing any start, pause, reset etc.).
Suggestions
Always create MediaPlayer instance in onCreate().
Release MediaPlayer
instance in onDestroy() Use in between.
Use start/pause/reset APIs in between create and release.
Its probably because of the "mp.release()":
As you can see in the documentation here, it state that after release(), the object is no longer available.
So, what i would suggest here is you may just remove the "mp.release()" and put it under onDestroy() of your activity.

Text To Speech app UI is slow android

In my app I am using TTS. I have 20 different activities which are changed when the user swipe left or right. According the activity, a text is spoken. I am executing tts with separate thread and activity selection is done with main thread. But the problem is very slow, the UI feels slugish. When I swipe left or right, once tts is finished speaking the text, the activity changes which shouldn't happen because I am using separate thread for tts.
Here is the codE:
TTS class:
public class textToSpeech {
TextToSpeech tts=null;
public textToSpeech(Context con)
{
tts = new TextToSpeech(con,new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) // initialization me error to nae ha
{
tts.setPitch(1.1f); // saw from internet
tts.setSpeechRate(0.4f); // f denotes float, it actually type casts 0.5 to float
tts.setLanguage(Locale.US);
}
}
});
}
public void SpeakText (String text)
{
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null); // TextToSpeech.QUEUE_FLUSH forces the app to stop all the sounds that are currently playing before speaking this text
}
public void stopSpeak()
{
tts.stop();
}
Gesture Reader Class: (separate class)
public void decideAlphabet()
{
tts.stopSpeak();
threadForTTS.start();
switch (i)
{
case 0:
activities=null;
activities = new Intent(contxt,A.class);
contxt.startActivity(activities);
break;
case 1:
activities=null;
activities = new Intent(contxt,B.class);
contxt.startActivity(activities);
break;
....... 20 more case statements for selecting activities
}
decideActivity() method is called when it is checked, which swipe was made, swipe to right or left.
NOTE:
Before adding tts in this app, the UI was performing properly without lag or slowness. After I added TTS, the app became slow. How can I solve this problem
Regards
I had the same problem and was about to comment on seeing the following logcat error ...skipped x many frames. The application may be doing too much work on its main thread.
Of course I was sure TTS was being called from another thread which I checked using Thread.currentThread().getName() But it turns out however that OnInit was indeed still running on the main thread and it looks like setting the language is an expensive operation. A quick change to run contents of onInit in a new thread and the UI freezing/choreographer complaining stopped:
#Override
public void onInit(int status) {
new Thread(new Runnable() {
public void run() {
if(status != TextToSpeech.ERROR) // initialization me error to nae ha
{
tts.setPitch(1.1f); // saw from internet
tts.setSpeechRate(0.4f); // f denotes float, it actually type casts 0.5 to float
tts.setLanguage(Locale.US);
}
}
}
}).start()

MediaPlayer playback not starting when using Service?

I am making an app which streams music. I am using a service to play music from an online mp3 file in the background. But the the service stops at prepareAsync() and never completes the preparation, and thus the music playback does not start. ie. The onPrepared() method is never called. Note: I used the same code in an activity instead of a service and this problem does not occur. What is wrong here? The code:
public class mp3playerservice extends IntentService implements OnPreparedListener {
String track;
String info[];
String name;
MediaPlayer mp;
Bundle extras;
public mp3playerservice() {
super("mp3playerservice");
}
// Will be called asynchronously be Android
#Override
protected void onHandleIntent(Intent intent) {
extras = intent.getExtras();
info=extras.getStringArray("info");
track=info[1];
name=info[0];
mp= new MediaPlayer();
if(mp.isPlaying()){
mp.release();
mp=new MediaPlayer();
}
start1(track);
}
void start1(String a){
try{
mp.setDataSource(a);
mp.setOnPreparedListener(this);
mp.prepareAsync();
}catch(Exception e){
Log.d("error is "+e.toString(),"error came up");
}
}
public void onPrepared(MediaPlayer mp4){
mp.start();
Log.d("in here2","okay");
}
}
It would have been great if you had also posted the logcat being generated. However, since you are subclassing from IntentService, it appears that once your call to prepareAsync() completes, the service stops itself. The reason for that is because at that point you have effectively finished handling the intent. At this point there are several different ways to fix this. The quickest way, but not the best way, is to change your code so that you call prepare() instead of prepareAsync() and then start() the player and comment out the line that registers the onPreparedListener as well. The best way in my opinion would be to subclass directly from Service and override onStartCommand().

MediaPlayer loops when started from onPause()

I want to play a sound when onPause() of my Activity is called. To do so, I use the following code:
#Override
public void onPause()
{
super.onPause();
MediaPlayer player = MediaPlayer.create(this, Settings.System.DEFAULT_RINGTONE_URI);
player.setLooping(false);
player.start();
}
This works fine, but the sound keeps on playing forever. I tried adding an OnCompletionListener, but that didn't help (the Listener is never called).
I know that I'm not calling player.stop() and player.release() anywhere, but I wouldn't even know where to do so.
My question is now: How can I make the sound play only once? Is there a way to wait for the media player to finish before the application goes to the background?
Ok, I found the solution.
The problem was, that I was using Settings.System.DEFAULT_RINGTONE_URI, which apparently never stops playing.
Using Settings.System.DEFAULT_NOTIFICATION_URI instead fixed the issue.
You can try this (if I've understood correctly)
public boolean test=false; // At begin
public void onPause()
{
super.onPause();
if(!test){
MediaPlayer player = MediaPlayer.create(this, Settings.System.DEFAULT_RINGTONE_URI);
player.setLooping(false);
player.start();
test=true;
}
}
Maybe I don't understand what you want to say. If you explain us a little bit more, maybe we can help to you :)
I haven't done this,, but I think you can check this one
player.setLooping(false);
player.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
player.stop();
player.release();
}
});
Not sure why it plays in loop but you can you use MediaElement to play sound? You can identify when media is ended by using method MediaEnded and then call stop method to stop playing audio

Categories

Resources