I've set MediaPlayer to play different songs. However, when I try to close the Application, the Activity gets closed, but the song still run in the Background. Here is how I've coded it!
try {
mp.setDataSource(text);
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mp.prepare();
mp.setVolume(0.4f, 0.4f);
songPlayer.setDataSource(song);
songPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer songPlayer) {
songPlayer.start();
}
});
songPlayer.prepare();
songPlayer.setLooping(true);
voicePlayer.setDataSource(voice);
voicePlayer.setLooping(true);
voicePlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer voicePlayer) {
voicePlayer.start();
}
});
voicePlayer.prepare();
voicePlayer.setVolume(0.5f,0.5f);
}
catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch (IllegalMonitorStateException e)
{
e.printStackTrace();
}
//THIS IS WHERE I THINK THE ERROR IS :
//WHERE `mp` IS LOOPED WITH DELAY OF 5000ms
try {
final Handler hlr = new Handler();
final Runnable looper = new Runnable() {
#Override
public void run() {
if (mp != null) {
if (mp.isPlaying()) {
mp.stop();
}
}
mp.start();
}
};
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
hlr.postDelayed(looper, 5000);
}
});
}
catch(IllegalStateException e)
{
e.printStackTrace();
}
}
}
And there is also One method which restarts the activity after a specified time. And the code for that Activity is :
public void snoozeup(View view)
{
SharedPreferences sa = getSharedPreferences("SnoozeList", Context.MODE_PRIVATE);
int snox = sa.getInt("SnoozeX",0);
if(snox==2) {
Handler handler = new Handler();
Runnable x = new Runnable() {
#Override
public void run()
{
Intent intent = new Intent(Time_Date.this, Time_Date.class);
intent.putExtra("finisher", state);
startActivity(intent);
}
};
handler.postDelayed(x, 120000);
}
else
{
Handler handler = new Handler();
Runnable x = new Runnable() {
#Override
public void run() {
startActivity(new Intent(Time_Date.this, Time_Date.class));
}
};
handler.postDelayed(x, 180000);
}
try
{
if (mp != null && mp.isPlaying())
{
Log.d("TAG------->", "mp is running");
mp.stop();
Log.d("TAG------->", "mp is stopped");
mp.reset();
mp.release();
Log.d("TAG------->", "mp is released");
mp=null;
}
if (voicePlayer != null && voicePlayer.isPlaying()) {
Log.d("TAG------->", "voiceplayer is running");
voicePlayer.stop();
Log.d("TAG------->", "voiceplayer is stopped");
voicePlayer.release();
Log.d("TAG------->", "voiceplayer is released");
}
if (songPlayer != null && songPlayer.isPlaying()) {
Log.d("TAG------->", "songplayer is running");
songPlayer.stop();
Log.d("TAG------->", "songplayer is stopped");
songPlayer.release();
Log.d("TAG------->", "songplayer is released");
}
}
catch(Exception e)
{
e.printStackTrace();
}
finish();
}
The problem is with mp . Other instances of MediaPlayer gets stopped. But not mp. And sadly, Can't see any error in logcat as well. So where am I doing wrong? Any help will be appreciated.
In order to stop the music you should put this code in the onPause() method.
This method can be overrided from your class that inherite from Activity
#Override
protected void onPause() {
super.onPause();
mp.stop
}
You can also take a look at Managing the Activity Lifecycle to better understand how an activity is managed by Android.
You are destroying your activity, but you need to stop/destroy your media player too. Please write down the following code in your activity.
#Override
public void onDestroy() {
super.onDestroy();
if (mp!= null) {
//destory ur object here.
}
}
Put in either onPause() or onDestroy() Example:
#Override
protected void onPause() {
super.onPause();
mp.stop();
}
Related
I have a problem with the Android MediaPlayer. As soon as a new sound file is clicked by user input, the old one does not stop, so all audio files overlap.
I already tried common methods like MediaPlayer.stop(); and
MediaPlayer.release();
These methods always result in an app crash, although they are called in the correct order
public void Abspielen(String Datei) {
try {
AndreasPlayer = MediaPlayer.create(MainActivity.this, getResources().getIdentifier(Datei, "raw", getPackageName()));
AndreasPlayer.start();
} catch (Exception e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Abspielen("filename");
}
I worked out the following solution:
public void Abspielen(String Datei) {
try {
stopKnopf = findViewById(R.id.fab2);
stopKnopf.show();
try {
if (AndreasPlayer.isPlaying()) {
AndreasPlayer.reset();
}
} catch (Exception ex) {
}
AndreasPlayer = MediaPlayer.create(MainActivity.this, getResources().getIdentifier(Datei, "raw", getPackageName()));
AndreasPlayer.start();
stopKnopf.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
AndreasPlayer.reset();
stopKnopf.hide();
}
});
AndreasPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
AndreasPlayer.reset();
stopKnopf.hide();
}
});
} catch (Exception e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
}
It works for a few buttons, but when I tap about 6 then only some of them work. The ones that don't work give the error (1, -19). I do the media player state wrapper set up, so if I need to use that to get states of my "mp"s, let me know.
public class SoundFile {
public SoundFile(final Activity activity, final String soundfile, int imgButtonId, ArrayList<MediaPlayerStateWrapper> mps) {
this.mp = new MediaPlayerStateWrapper();
try {
this.afd = activity.getAssets().openFd(soundfile + ".mp3");
} catch (IOException e) {
e.printStackTrace();
}
this.allMps = mps;
mps.add(this.mp);
this.position = (ImageButton) activity.findViewById(imgButtonId);
this.position.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
mp.reset();
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepareAsync();
mp.start();
}catch (Exception ex){
ex.printStackTrace();
}
....
You have to add an onPreparedListener. Here is what I did and it worked.
try {
mp = new MediaPlayer();
mp.reset();
try {
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IOException e) {
e.printStackTrace();
}
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mp.release();
}
});
mp.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mpm) {
mpm.start();
mp.start();
}
});
mp.prepareAsync();
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
}
The basic idea is if no face detected,it should return to Main(reset Activity) but after returning back to main ,getCameraInstance(0) returns null.
If i want to back to Main ,it will call the onPause() and release the cam and after main re-created the backCamera is already relased and it should problem-free create a new instance of back camera.Am i wrong ?
Thanks
ps :i get java.lang.RuntimeException: Fail to connect to camera service and that means i didnt release the camera correctly but i cant find my error.
Here is my code
public class MainActivity extends Activity{
....
private Camera mCameraBack=null;
private CameraPreviewBack mPreviewBack;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mCameraBack==null){
mCameraBack=getCameraInstance(0);
}
try{
mPreviewBack=new CameraPreviewBack(this,mCameraBack );
previewBack=(FrameLayout)findViewById(R.id.camera_preview_back);
previewBack.addView(mPreviewBack);
}catch(Exception ex){
Log.d(TAG,"surfaceCreate");
ex.printStackTrace();
}
public void capture(View view){
mPreviewBack.takePicture();
...
}
#Override
protected void onPause() {
Log.d(TAG, "onPause");
super.onPause();
if (mCameraBack != null) {
mCameraBack.stopPreview();
mCameraBack.release();
mCameraBack = null;
}
if (mPreviewBack != null) {
previewBack.removeView(mPreviewBack);
mPreviewBack = null;
}
}
#Override
public void onResume() {
Log.d(TAG, "onResume");
super.onResume();
if (mCameraBack == null) {
mCameraBack = getCameraInstance(0);
}
if (mPreviewBack == null) {
mPreviewBack=new CameraPreviewBack(this,mCameraBack );
previewBack.addView(mPreviewBack);
}
}
public static Camera getCameraInstance(int cameraId){
Camera c = null;
try {
c = Camera.open(cameraId);
}
catch (Exception e){
}
return c; // returns null if camera is unavailable
}
}
and
public class CameraPreviewBack extends SurfaceView implements SurfaceHolder.Callback {
...
public CameraPreviewBack(Context context,Camera camera) {
super(context);
mCamera=camera;
this.context=context;
mHolder=getHolder();
mHolder.addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "Surface created");
try {
if(mCamera!=null){
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(TAG, "mHolder failure");
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d(TAG, "Surface changed");
configureCamRotation();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void takePicture(){
..
task.execute();
try {
task.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
task.cancel(isFinished);
}
private PictureCallback getPictureCallback() {
PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera){
....
if(!detected){
Intent intentMain=new Intent(context, MainActivity.class);
intentMain.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intentMain);
}
...
}
private class TakePictureTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
mCamera.takePicture(null, null, getPictureCallback());
try {
Thread.sleep(2000); // 3 second preview
} catch (InterruptedException e) {
}
return null;
}
}
newer swallow exceptions
like here:
catch (Exception e){
}
Print this exception Log.d(TAG, "Error when init camera", e); and maybe you will get:
Runtime Exception http://developer.android.com/reference/android/hardware/Camera.html#open(int)
releasing camera onDestroy and changing Intents in onPostExecute method of Asynctask solved my problem
I have some working code, which takes a few buttons and when they are pressed, plays some audio files. However, this code seems uncessearily large and I feel it could be reduced down into smaller methods that could be called. I have, however, taken enough time and effort just to get this working so I can't see how to reduce it. Can you provide a cleaner / smaller and more resuable way of calling audio tracks as this code will only get larger as I intend to have around 30 tracks.
audioBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mediaPlayer != null && mediaPlayer.isPlaying())
{
mProgressStatus = 0;
mediaPlayer.stop();
try {
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
progressBar1.setProgress(mProgressStatus);
mHandler.removeCallbacks(runnable1);
t.interrupt();
audioBtn2.setEnabled(true);
audioBtn3.setEnabled(true);
} else {
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.song1);
mediaPlayer.start();
t = new Thread(runnable1);
t.start();
mProgressStatus = 0;
progressBar1.setProgress(mProgressStatus);
audioBtn2.setEnabled(false);
audioBtn3.setEnabled(false);
}
}
});
audioBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mediaPlayer != null && mediaPlayer.isPlaying())
{
mProgressStatus = 0;
mediaPlayer.stop();
try {
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
progressBar2.setProgress(mProgressStatus);
mHandler.removeCallbacks(runnable2);
t.interrupt();
audioBtn1.setEnabled(true);
audioBtn3.setEnabled(true);
} else {
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.song2);
mediaPlayer.start();
t = new Thread(runnable2);
t.start();
mProgressStatus = 0;
progressBar2.setProgress(mProgressStatus);
audioBtn1.setEnabled(false);
audioBtn3.setEnabled(false);
}
}
});
audioBtn3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mediaPlayer != null && mediaPlayer.isPlaying())
{
mProgressStatus = 0;
mediaPlayer.stop();
try {
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
progressBar3.setProgress(mProgressStatus);
mHandler.removeCallbacks(runnable3);
t.interrupt();
audioBtn1.setEnabled(true);
audioBtn2.setEnabled(true);
} else {
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.song3);
mediaPlayer.start();
t = new Thread(runnable3);
t.start();
mProgressStatus = 0;
progressBar3.setProgress(mProgressStatus);
audioBtn1.setEnabled(false);
audioBtn2.setEnabled(false);
}
}
});
}
private Runnable runnable1 = new Runnable() {
public void run() {
try {
while (mProgressStatus < 30) {
mProgressStatus++;
mHandler.post(new Runnable() {
public void run() {
progressBar1.setProgress(mProgressStatus);
}
});
Thread.sleep(1000);
}
} catch (InterruptedException e) {
mProgressStatus = 0;
mHandler.removeCallbacks(runnable1);
}
}
};
private Runnable runnable2 = new Runnable() {
public void run() {
try {
while (mProgressStatus < 30) {
mProgressStatus++;
mHandler.post(new Runnable() {
public void run() {
progressBar2.setProgress(mProgressStatus);
}
});
Thread.sleep(1000);
}
} catch (InterruptedException e) {
mProgressStatus = 0;
mHandler.removeCallbacks(runnable2);
}
}
};
private Runnable runnable3 = new Runnable() {
public void run() {
try {
while (mProgressStatus < 30) {
mProgressStatus++;
mHandler.post(new Runnable() {
public void run() {
progressBar3.setProgress(mProgressStatus);
}
});
Thread.sleep(1000);
}
} catch (InterruptedException e) {
mProgressStatus = 0;
mHandler.removeCallbacks(runnable3);
}
}
};
One thing I've already looked at is moving the setting of buttons to enabled/disabled to a separate class, but that involves creating more large un-resuable scripts to handle calling the main thread (As I need to reset the buttons in the runnable threads after songs have finished)
I'm also not sure if it's possible to pass element ids as arguments to functions, in which case that would help reduce the code.
You can reduce duplicate codes by defining an abstract OnClickListener class and delegate the responsibility of the "different" parts to whoever extends it. You can of course define this as an Inner Class to access the parameters of the current class. this is called Template method pattern
first define MyClickListener:
public abstract class MyClickListener extends View.OnClickListener {
#Override
public void onClick(View v) {
if(mediaPlayer != null && mediaPlayer.isPlaying())
{
mProgressStatus = 0;
mediaPlayer.stop();
try {
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
setProgress(mProgressStatus);
mHandler.removeCallbacks(runnable1);
t.interrupt();
enableButtons(true);
} else {
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.song1);
mediaPlayer.start();
t = getThread();
t.start();
mProgressStatus = 0;
setProgress(mProgressStatus);
enableButtons(false);
}
}
public abstract void setProgress(int progress);
public abstract void enableButtons(boolean enable);
public abstract Thread getThread();
}
then use it like this:
audioBtn1.setOnClickListener(new MyClickListener(){
public abstract void setProgress(int progress){
progressBar1.setProgress(progress);
}
public abstract void enableButtons(boolean enable){
audioBtn2.setEnabled(enable);
audioBtn3.setEnabled(enable);
}
public abstract Thread getThread(){
return new Thread(runnable1);;
}
})
And so on for other buttons.
You can apply this pattern for the runnables too!
I need help to set duration of MediaPlayer on start activity.
I have tried using seekTo() but its not working correctly.
Here is what I'm doing:
protected void Player(String bURL, int seekTo){
btn = (Button) findViewById(R.id.playpauseBtn);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(bURL);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (!mediaPlayer.isPlaying()) {
if (seekTo != 0) {
mediaPlayer.seekTo(seekTo);
}
mediaPlayer.start();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
Try to modify to this:
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (!mp.isPlaying()) {
if (seekTo != 0) {
mp.seekTo(seekTo);
}
mp.start();
}
}
});
mediaPlayer.setDataSource(bURL);
mediaPlayer.prepareAsync();