I use media player to play sounds on my application. It works just fine.
I am playing sound on a separated thread. Even thought, part of the sound plays before activity appear.
I tried to play sound onCreate method. it didn't work. onStart and
onResume. it has some problems. it plays every time activity resumed.
sometimes while I am not even touching the device!
What is the best way to play sound after activity appears?
public boolean played = false;
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if (!played)
Settings.playSound(dvd.titleImageName.replace("png", "mp3"), this);
played = true;
}
public static MediaPlayer mp = null;
public static void playSound(String fileName, Context c)
{
//MediaPlayer mp = MediaPlayer.create(c, resId);
if (mp!=null)
{
mp.stop(); //error
mp.reset();
mp.release();
}
mp = new MediaPlayer();
AssetFileDescriptor descriptor;
try {
descriptor = c.getResources().getAssets().openFd("sounds/" + fileName);
mp.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
descriptor.close();
mp.prepare();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (mp == null) return;
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
}
});
mp.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
}
});
mp.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
#Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
// TODO Auto-generated method stub
}
});
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
mp.start();
}
}).start();
}
Your played variable only works while activity is alive. If it gets killed, played doesn't retain. For example, rotate your device an you'll hear sound playing again.
save state (played) in onSavedInstanceState bundle and restore it in onCreate
Play in in OnCreate or onResume
Related
I am fairly new to programming and having a tough time with a small problem. I have created an object which is initialized easily and starts working, how do i stop that object from functioning.
Following is my code:
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
animationFart();
playRandomSound();
}
private void playRandomSound() {
// TODO Auto-generated method stub
int randomInt = (new Random().nextInt(soundList.size()));
int sound = soundList.get(randomInt);
MediaPlayer mp = MediaPlayer.create(btn.getContext(), sound);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
});
How can i stop this with the press of a button.
Define MediaPlayer mp; globally and use mp.stop();:
if (mp!=null && mp.isPlaying()) {
mp.stop();
}
use this class
public class AudioPlayer {
private MediaPlayer mediaPlayer;
public void play(Context context, int resId) {
stop();
mediaPlayer = MediaPlayer.create(context, resId);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
stop();
}
});
mediaPlayer.start();
}
public void stop() {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
}
public boolean isPlaying() {
return mediaPlayer != null;
}
}
I'm trying to create an app that play a certain audio file, that was previously recorded, when I press a button or shake my phone. Here is my code.
public class Reproduzir extends Activity implements SensorEventListener{
MediaPlayer player = new MediaPlayer();
SensorManager sensor;
#Override
protected void onCreate(Bundle savedInstanceState ){
super.onCreate(savedInstanceState);
sensor= (SensorManager) getSystemService(SENSOR_SERVICE);
setContentView(R.layout.reproduzir);
Button reproduzir = (Button) findViewById(R.id.reproduzir);
reproduzir.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
play();
}
});
Button fechar= (Button) findViewById(R.id.fechar);
fechar.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (player.isPlaying()) {
player.stop();
player.release();
}
finish();
}
});
}
public void play(){
try {
player.setDataSource(Environment.getExternalStorageDirectory().getPath()+"/2cp.3gp");
player.prepare();
player.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();
}
}
public void onStart(){
super.onStart();
sensor.registerListener(this,sensor.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if(event.values[0]>10.2
||event.values[1]>10.2
||event.values[2]>10.2){
play();
}
}
}
My problem is that when I run it, I can only play it once. If I press the button a second time or shake it again, it does nothing. Can anyone help?
The easy fix is to simply add player.reset() in your play() method BEFORE calling player.setDataSource(...).
You can only call setDataSource(...) once without resetting the player. It is legal to call reset() in any state however (even if the player isn't yet initialized).
In other words, even if it's the first time you've called play() it is OK to use the following code in your play() method...
try {
player.reset();
player.setDataSource(Environment.getExternalStorageDirectory().getPath()+"/2cp.3gp");
player.prepare();
player.start();
}
// Your catch blocks here
Try to use:
mediaPlayer.reset()
after:
mediaPlayer.stop()
instead of release.
You can only set data source once.
in you code everytime the user presses the button you do this:
player.setDataSource(Environment.getExternalStorageDirectory().getPath()+"/2cp.3gp");
whice is wrong.
you need to setdata and prepare once and play how many times you want.
like so:
put this in you onCreate:
try {
player.setDataSource(Environment.getExternalStorageDirectory().getPath()+"/2cp.3gp");
player.prepare();
player.start();
in the onClick(View v), just have :
player.play();
Long story short - you have to use:
setLooping(true)
For more information about the Media Player check the post below. Take in mind the state diagram
http://developer.android.com/reference/android/media/MediaPlayer.html
MediaPlayer State diagram
I have a Fragment with a ListView which is a list of sounds, that is populated in this way:
MediaPlayer mMediaPlayer;
listview.setAdapter(new ListAdapter(getActivity(), tit, desc, songs, filenames, mMediaPlayer));
MediaPlayer is given as parameter because i would like that when back button is pressed or app goes in background, the player would stop playing.
So i have override onPause and onDestroy method in my Fragment, but this just doesn't work. Sound continues playing even if app is closed. This is my code:
#Override
public void onDestroy() {
// TODO Auto-generated method stub
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
super.onDestroy();
}
#Override
public void onPause() {
// TODO Auto-generated method stub
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
super.onPause();
}
I play sounds in my BaseAdapter class, in this way:
public void playSound2(int pos){
if(isPlaying){
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
isPlaying = false;
}
mMediaPlayer = MediaPlayer.create(context, songs[pos]);
mMediaPlayer.start();
isPlaying = true;
}
Do you have any suggestion? Thank you.
My first suggestion is: don't use the adapter to interact with the media player. Instead, attach an item click listener to your listview, like this
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
...
}});
and do whatever you want with the media player in the onItemClick callback.
That being said, you should reset your media player when inside your onclicklistener, like so
try {
mPlayer.reset();
mPlayer.setDataSource(trackToBePlayed); //trackToBePlayed is dependent on the select position
mPlayer.setOnPreparedListener(mPreparedListener);
mPlayer.prepareAsync();
} catch (IOException e) {
} catch(IllegalArgumentException e) {
}
And in the mPreparedListener, when ready, you do
mPreparedListener = new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
};
This should be enough to point you in the right direction :)
i have a problem. my media player doesn't stop even activity has stopped. so i confuse why media player doesn't stop. media player immediately playing until a mp3 finish. here my code
public class Isi_TakbiratulIhram extends Activity{
MediaPlayer mp;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.isitakbiratulihram);
ImageButton iftitah1=(ImageButton) findViewById (R.id.takbiratulihram1);
iftitah1.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
go();
}
public void go(){
if(mp != null ){
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.seekTo(0);
mp = null;
}
else {
mp=MediaPlayer.create(Isi_TakbiratulIhram.this, R.raw.iftitah1);
mp.start();
}
}});
thanks for help
Override Activity onPause() method for stoping Media Player :
#Override
public void onPause(){
super.onPause();
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
You can override onPause() or onStop() and stop it there:
#Override protected void onPause()
{
if(mp != null ){
mp.stop();
// mp.release(); ??
}
super.onPause();
}
When user stops an Activity the state of activity can go to onStop() state,SO it is required to stop any ongoing tasks like music playing here.So in android programming it's required go handle all states like onRestart(), onResume(), onStop(), onPause(), onDestroy() for proper functioning of the program.
For handling stopping and restarting of activity visit :
http://developer.android.com/training/basics/activity-lifecycle/stopping.html
I'm playing video via MediPlayer in my android application and have SeekBar displayed. Now I want this seeks bar to automatically update as the video progresses so it should automatically move from left to right. At the moment, (code below) the bar updates and this is done via running thread, that every second updates the progress of seekBar. The problem is it is not smooth and as seekBar is updated via its seekProgress() the video stops for split second and all is very jumpy. Now I would like it to have updated more often then every second as well as keep functionality that I already implemented to allow user to tap on the bar and change progress of the video.
I'm after something like Android MediaPLayer application have, seekBar is on transparent background and all is smooth and I have no idea how it is done.
No, currently as you see from the code below thread updates every second as it sleeps inside f run method. I've also tried to use handlers to update UI thread, effect was the same. I also extended SeekBar to its own class, had thread there and this was no good either, exactly same effect.
If anyone can explain to me how to solve this problem and how its done with other player appls that would be great.
public class FightPlayerActivity extends Activity implements Runnable, OnSeekBarChangeListener, SurfaceHolder.Callback, OnPreparedListener {
private MediaPlayer mp=null;
private SeekBar seekBar;
private Thread progressBarUpdater;
private String filePath;
private Handler handler=new Handler();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Toast.makeText(this,"Create ", 2000).show();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void onStop()
{
super.onStop();
mp.stop();
mp.reset();
mp.release();
}
public void run()
{
while(true)
{
try {
progressBarUpdater.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
seekBar.setProgress(mp.getCurrentPosition());
// handler does have same effect, so video stops for split second
//handler.postDelayed(this, 1000);
}
}
public void onStart()
{
super.onStart();
setContentView(R.layout.fight_player);
filePath=getIntent().getStringExtra("filename");
filePath=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+"/FightAll_BJJ_Scoring/"+filePath;
Toast.makeText(this,filePath, 2000).show();
// seek bar
seekBar=(SeekBar) findViewById(R.id.seek_bar);
seekBar.setOnSeekBarChangeListener(this);
try {
SurfaceView sv=(SurfaceView) findViewById(id.video_preview);
SurfaceHolder sh=sv.getHolder();
sh.addCallback(this);
sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
} 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();
}
}
public void stop(View view)
{
mp.seekTo(0);
mp.pause();
}
public void pause(View view)
{
mp.pause();
}
public void play(View view)
{
mp.start();
}
public void surfaceCreated(SurfaceHolder holder) {
try {
mp=new MediaPlayer();
mp.setDataSource(filePath);
mp.setDisplay(holder);
mp.setOnPreparedListener(this);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.prepare();
//handler.removeCallbacks(this);
//handler.postDelayed(this, 1000);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
public void onPrepared(MediaPlayer mediaplayer) {
mp.start();
seekBar.setMax(mp.getDuration());
progressBarUpdater=new Thread(this);
progressBarUpdater.start();
//handler.postDelayed(this, 1000);
}
public void onProgressChanged(SeekBar sb,int progress,boolean fromUser)
{
//Toast.makeText(this, progress, 2000).show();
mp.seekTo(progress);
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
onProgressChanged(seekBar,seekBar.getProgress(),true);
}
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
Your major problem is in your onProgressChanged() method.
You are seeking to the specified position every time the seekBar progress changes, even when it is done programmatically. Which means that every time you call seekBar.setProgress(mp.getCurrentPosition()), onProgressChanged() will be fired.
So we change it to the following:
public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) {
if (fromUser) {
mp.seekTo(progress);
}
}
That way it will only be fired when the user moves the seekBar.
Moreover, according to this answer, it would be better to replace your while(true) loop with:
public void run() {
seekBar.setProgress(mp.getCurrentPosition());
if (mp.getCurrentPosition() < mp.getDuration()) {
seekBar.postDelayed(this, MILLISECONDS);
}
}