I am using a TextureView to play a video in a ListView. The TextureView itself works perfectly, however, if I press the home button and reenter the application a few times, the TextureView turns black (though the audio continues to play). If I exit and reenter again, the TextureView turns white (or maybe transparent, as white is the colour of my background).
Here is my code:
holder.instagramTextureView
.setSurfaceTextureListener(new SurfaceTextureListener() {
#Override
public void onSurfaceTextureUpdated(
SurfaceTexture surface) {
// TODO Auto-generated method stub
}
#Override
public void onSurfaceTextureSizeChanged(
SurfaceTexture surface, int width, int height) {
// TODO Auto-generated method stub
}
#Override
public boolean onSurfaceTextureDestroyed(
SurfaceTexture surface) {
// TODO Auto-generated method stub
return false;
}
#Override
public void onSurfaceTextureAvailable(
SurfaceTexture surface, int width, int height) {
final Surface s = new Surface(surface);
try {
holder.mMediaPlayer = new MediaPlayer();
holder.mMediaPlayer.setDataSource(post
.getMedias().get(0)
.getMediaUrlVideomp4StandardRes());
holder.mMediaPlayer.setSurface(s);
holder.mMediaPlayer.prepare();
holder.instagramVideoVolume = 0f;
holder.mMediaPlayer.setVolume(
holder.instagramVideoVolume,
holder.instagramVideoVolume);
//holder.mMediaPlayer.setOnBufferingUpdateListener(this);
holder.mMediaPlayer
.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(
MediaPlayer mp) {
// To play:
mp.reset();
try {
mp.setDataSource(post
.getMedias()
.get(0)
.getMediaUrlVideomp4StandardRes());
mp.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch
// block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch
// block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch
// block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch
// block
e.printStackTrace();
}
// <--- Here comes a call to
// "To Resize" which is shown
// right above this code
mp.start();
}
});
// holder.mMediaPlayer.setOnPreparedListener(this);
//holder.mMediaPlayer.setOnVideoSizeChangedListener(this);
holder.mMediaPlayer
.setAudioStreamType(AudioManager.STREAM_MUSIC);
holder.mMediaPlayer.start();
holder.instagramTextureView
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (holder.instagramVideoVolume == 1) {
holder.instagramVideoVolume = 0f;
holder.mMediaPlayer
.setVolume(
holder.instagramVideoVolume,
holder.instagramVideoVolume);
} else {
holder.instagramVideoVolume = 1f;
holder.mMediaPlayer
.setVolume(
holder.instagramVideoVolume,
holder.instagramVideoVolume);
}
}
});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Problem was making a new mediaplayer each time the surface is available. Not quite sure how this worked, but this was the problem. Instead, I create the mediaplayer outside of this listener.
From my research, textureView.getSurfaceTexture() returns null onResume(). What I did was reattach a listener to it in onResume().
TextureView textureView;
/*....
Usual stuff
*/
public void onPause(){
super.onPause();
//... destroy or disable image producer
}
public void onResume(){
super.onResume();
textureView.setSurfaceTextureListener(/*another listener*/);
}
Then, perform your usual things on onSurfaceTextureAvailable()
The black screen and audio playing happened with me when I did not release the MediaPlayer object.
Related
I'd like to switch the video method in MediaPlayer to TextureView's Surface at some point during playback. But all I get is a black screen (the sound is playing). I made sure the size of the TextureView is ok, so it's not the case.
If I set the Surface of TextureView before calling prepare on MediaPlayer, than the video is shown.
So it seems that the order of calling prepare and applying the surface is crucial.
What's interesting, in case of SurfaceView everything works fine (no matter when I set the holder of SurfaceView: before or after the preparing is done).
Is there a way to set TextureView to MediaPlayer during playback? Calling MediaPlayer.release() and recreating it again while having to take care of progress would be very inconvenient.
#Override
public void onSurfaceTextureAvailable(final SurfaceTexture surface, final int width, final int height) {
s = new Surface(surface);
Thread play = new Thread(new Runnable() {
#Override
public void run() {
try {
player = new MediaPlayer();
player.setSurface(s);
player.setDataSource(vidAddress);
player.prepare();
player.setOnPreparedListener(MainActivity.this);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnCompletionListener(MainActivity.this);
player.setScreenOnWhilePlaying(true);
Log.e("mediaplayer", "true");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
play.start();
}
And your onPrepared listener like this
public void onPrepared(MediaPlayer mp) {
if (!player.isPlaying()) {
player.start();
}
}
setSurfaceTextureListener like this at onCreate
mTextureView.setSurfaceTextureListener(MainActivity.this);
I hope this will help :)
I'm loading audio sounds into a listview, I play them.When the audio playing is done, i want to change that specific sound's pause button to play button again.
here is my code to play sounds
soundChild.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
player.setDataSource(url);
// file.close();
player.prepare();
player.setLooping(false);
// player.start();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (player.isPlaying()) {
if (player != null) {
player.pause();
// Changing button image to play button
soundChild.setImageResource(R.drawable.playbutton);
}
} else {
// Resume song
if (player != null) {
player.start();
// Changing button image to pause button
soundChild.setImageResource(R.drawable.pausebutton);
}
}
}
});
player.setOnCompletionListener(new OnCompletionListener() {
#Override public void onCompletion(MediaPlayer mp) { // TODO
// Auto-generated method stub player.release(); player=null;
Toast.makeText(_context, "complete", Toast.LENGTH_LONG).show();
soundChild.setImageResource(R.drawable.playbutton);
player.reset();
} });
But on complete listner the imageview of player button is never changed back to play imageview again. I doin't know where i'm doing wrong, because if onComplete is being called then imageview background should also change.please help.
Usually You have to call requestLayout before:
soundChild.requestLayout();
soundChild.setImageResource(R.drawable.playbutton);
and then after changing the image
soundChild.invalidate();
What else could You try? If it doesn´t work, You can also try:
soundChild.setImageDrawable(context.getResources().getDrawable(R.drawable.playbutton));
Because, like described in the API for setImageResource:
This does Bitmap reading and decoding on the UI thread, which can
cause a latency hiccup
Also, what it is possible, You have to call it in on ui thread:
runOnUiThread(new Runnable() {
#Override
public void run() {
soundChild.setImageResource(R.drawable.playbutton);
}
});
and call this in onCompletion.
In android, I have a mediaplayer on detail screen, which duplicates when I select another screen then play another detail, causing sound files to play on the same time. how do I fix this problem? Id like to play the most recent selected media only.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feeddetail);
tc_recDurat = (TextView)findViewById(R.id.recDetDurat);
tc_recDuratBack = (TextView)findViewById(R.id.recDetDuratBack);
TextView tc_recPath = (TextView)findViewById(R.id.recDetPath);
recPath = (String) intent.getSerializableExtra("INTENT_PATH");
tc_recPath.setText(recPath);
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(recPath);
} catch (IOException e1) {
// TODO Auto-generated catch block
Toast.makeText(getApplicationContext(), e1.getLocalizedMessage(), Toast.LENGTH_LONG);
}
ImageButton mClickButton1 = (ImageButton)findViewById(R.id.btnPlay);
mClickButton1.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (mediaPlayer !=null){
try {
mediaPlayer
mediaPlayer.prepare();
seekBar.setMax(mediaPlayer.getDuration());
mediaPlayer.start();
seekUpdate();
isPlaying = true;
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
ImageButton mClickButton2 = (ImageButton)findViewById(R.id.btnStop);
mClickButton2.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
mediaPlayer.stop();
isPlaying = false;
}
});
I am not sure what your problem is, but i believe you are trying to say that as you change through different activities, the sounds files do not stop playing
In that case you can do the following
In the activity
You can override the onPause method and put mediaPlayer.stop() inside it
#Override
public void onPause() {
super.onPause();
mediaPlayer.stop();
}
I am trying to run audios one after another with a time gap of 5 seconds. However I dont really see that happening. My third audio in the list is played and others are skipped. This means while debugging only music3 is being played and others are not. I would love alternate methods of doing this. Moreover I used prepare method just like that. Makes no difference while running though.
for(int j=0;j<3;j++)
{
if(j==0)
{
xnp = MediaPlayer.create(this,R.raw.ticktock);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
xnp.prepare();
xnp.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 5000);
xnp.stop();
}
if(j==1)
{
xnp = MediaPlayer.create(this,R.raw.music2);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
xnp.prepare();
xnp.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 5000);
xnp.stop();
}
else if (j==2)
{
xnp = MediaPlayer.create(this,R.raw.music3);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
xnp.prepare();
xnp.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 5000);
xnp.stop();
intenter();
}
}
Your current implementation does not work because the media playback is not done on the main thread, so you are immediately playing all 3 media resources, so only the third one is heard.
I think you might want to call MediaPlayer#setOnCompletionListener on your MediaPlayer object. In the completion listener, you can then postDelayed onto your Handler to queue up the next resource to play.
I am streaming mp3 on media-player, it plays continuos when your screen is on or you are doing multitasking but when you turn off screen it won't play audio continuously, it stucks many times.And I got this "info/warning (702,0) "on log cat
I tried mp.setWakeMode(getBaseContext(),PowerManager.FULL_WAKE_LOCK);
I am using service to play audio streaming but still it stucks.
public class myPlayService extends Service{
MediaPlayer mp;
String link ="http://85.23.194.72:70/mp3/str";
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
mp = new MediaPlayer();
try {
mp.setDataSource(link);
mp.setWakeMode(getBaseContext(),PowerManager.FULL_WAKE_LOCK);
mp.prepareAsync();
mp.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.start();
}
});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}#Override public void onDestroy() { mp.stop();mp.release();}}