In the mainactivity I have create a handler as instance variable:
SeekBar seek_bar;
MediaPlayer player;
Handler seekHandler = new Handler();
Then I have the following two methods in the MainActivity to update the seekbar as the audio plays in media player:
public void getInit() {
seek_bar = (SeekBar) findViewById(R.id.seek_bar);
}
Runnable run = new Runnable() {
#Override
public void run() {
seekUpdation(); **//Exception comes here while closing the app**
}
};
public void seekUpdation() {
seek_bar.setProgress(mMediaPlayer.getCurrentPosition());
seekHandler.postDelayed(run, 1000);
}
The problem I am facing is that when the audio is running and user closes the application using device back buttton. I get NullPointerException. The destroy method of activity is:
#Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
Remove any queued messages/callbacks from the handler in your onDestroy. My bet is that its running the last message after onDestroy is called.
Related
I start a Thread in a Fragment and use an Interface call, to #Override a method in the Fragment starting the thread. This #Override stops a ProgressDialog and changes the Text of a TextView in the Fragment.
When I do the same in an Activity, there is no Problem but now when using a Fragment I got the "only Thread that creates a View can touch it's views" - Error. So I used getActivity().runOnUiThread(runnable) and posted the code to the MainThread, but why do I need to do this, since it works in a Activity without this? Did I made a mistake?
The Thread
//interface
private ConnectToDevice connectToDevice;
//C-Tor
public Thread_ConnectToDevice(BluetoothDevice device, ConnectToDevice connectToDevice ) {
this.mBluetoothDevice = device;
this.connectToDevice = connectToDevice;
}
//call
connectToDevice.connectionSuccess(false, null);
Fragment
//make Thread
thread_connectToDevice = new Thread_ConnectToDevice(mBluetoothDevice, Fragment_RoutineStartConnection_setPassword.this);
thread_connectToDevice.start();
//CallBack
//Thread Connect Success
#Override
public void connectionSuccess(final Boolean bSuccess,final BluetoothSocket mSocket) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if(bSuccess){
mProgessDialog.setTitle(R.string.tv_Fragmentsetpassword_Connected_CheckPW);
if(thread_connectedToDevice != null){
if(thread_connectedToDevice.isAlive()){
thread_connectedToDevice.interrupt();
}
}
thread_connectedToDevice = new Thread_ConnectedToDevice(mSocket, sTryingDonglePassword);
thread_connectedToDevice.start();
}else{
mProgessDialog.dismiss();
tv_Fragmentsetpassword_userhint
.setTextColor(getResources().getColor(R.color.Mercedes_RED, null));
tv_Fragmentsetpassword_userhint.setText(R.string.tv_Fragmentsetpassword_ConnectionFailed);
}
}
});
}
I have the feeling that I passed the wrong listener Instance to the Thread.
As asked this is the callback realized the same way but in a Activity:
Thread
//listener
private Finished_AskingForInformation listener;
//C-Tor
public Td_AskForInformation(
Finished_AskingForInformation listener) {
this.listener = listener;
}
//call
listener.AskingFinished();
Activity
//Create and start thread
td_askForInformation = new Td_AskForInformation(this);
td_askForInformation.start();
//CallBack
#Override
public void AskingFinished() {
mProgressDialog.dismiss();
}
I'm trying to make app like soundboard. Now I have small problem with playing the same sound after reset after playing 1st time.
final MediaPlayer SoundOne = MediaPlayer.create(this, R.raw.somesound);
final Button play_SoundOne = (Button) this.findViewById(R.id.play_SoundOne);
play_SoundOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SoundOne.start();
}
});
SoundOne.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
SoundOne.reset();
}
});
Can I get help how can I prepare that sound to play again after reset (I do reset to make space in memory for next sounds) but SoundOne.prepare() doesn't work if I put that before .start(). Any advice?
Based on the documentation:
It is a programming error to invoke methods such as getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioAttributes(AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() or prepareAsync() in the Idle state for both cases. If any of these methods is called right after a MediaPlayer object is constructed, the user supplied callback method OnErrorListener.onError() won't be called by the internal player engine and the object state remains unchanged; but if these methods are called right after reset(), the user supplied callback method OnErrorListener.onError() will be invoked by the internal player engine and the object will be transfered to the Error state.
You cannot immediately start() or prepare after reset(). Based on the documentation for reset:
Resets the MediaPlayer to its uninitialized state. After calling this method, you will have to initialize it again by setting the data source and calling prepare().
The solution would be
Initialize the MediaPlayer again -> set the Data Source -> call prepare.
Alternatively you can avoid performing reset onCompletion. Instead, release the MediaPlayer onStop()
You can update your as follows:
MediaPlayer soundOne = null;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
....
play_SoundOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
soundOne.start();
}
});
}
#Override
protected void onStart() {
super.onStart();
if(soundOne == null){
soundOne = MediaPlayer.create(this, R.raw.somesound);
soundOne.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//Don't reset
}
});
}
}
#Override
protected void onStop() {
super.onStop();
soundOne.release();
soundOne = null;
}
I am currently working on an android application with audio playing function. In the play_pause Activity, I have a seekbar and a button to control the audio.
public class PlayerActivity extend AppCompatActivity {
...
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
playerButton = (Button) findViewById(R.id.playButton);
playerButton.setOnClickListener(new Button.setOnClickListener() {
if (player != null) {
//load music to player
player.create(PlayerActivity.this, R.raw.music);
seekbar.setMax(player.getDuration());
mTimer = new Timer();
mTimerTask = new TimerTask() {
public void run() {
seekbar.setProgress(player.getCurrentPosition());;
}
};
mTimer.schedule(mTimerTask, 0, 10);
}
});
}
}
When I press the back button without hit the "play" button, my application can change activity successfully. However, once the "play" button has been clicked, I can not change activity. Below is the onDestroy() method.
protected void onDestroy() {
super.onDestroy();
player.release();
}
The Logcat has the error message saying
java.lang.IllegalStateException
at MediaPlayer.getCurrentPosition()
at PlayerActivity.run() //which is the mTimerTask
at java.util.Timer$TimerImpl.run()
Anyone have idea how to solve?
Cancel your Timer onDestroy of Activity too by calling
mTimer.cancle();
Exception raised due to call of player.getCurrentPosition(); after release of Media player instance on destroy of Activity as you timer thread dont stops.
I am opening a progressdialog with AsyncTask in doInBackground method the question is loading from database and after question successfully loaded the progress dialog box will be closed
but my problem is some time I am getting following error
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRoot$W#44757528 is not valid; is your activity running?
by doing some googling I have found that there may be i am holding on to a reference to a Context (either explicitly, or by creating a Dialog or Toast or some other dependent item) that has been destroyed (typically because you are using the onCreateDialog or you passed the Activity to some other process that didn't get destroyed when the Activity was destroyed).
So I have put below code that dismiss progressdialog in-case if activity is destroyed before dialog box is dismissed
protected void onDestroy() {
if (pdForNewQuestion != null)
pdForNewQuestion.dismiss();
super.onDestroy();
}
but I still face the issue. I am not destroying any activity but still the error suddenly comes sometimes and sometimes it works properly
the async code is below
// Start new question in every 60 seconds :)
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
mProgressStatus++;
} catch (Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
txtCountingNum.setText((timer--) + "\nSec.");
if (timer < 0) {
questionLoadWithAsyncTask();
}
}
});
}
}
}).start();
public void questionLoadWithAsyncTask() {
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
pdForNewQuestion = new ProgressDialog(QuizActivity.this);
pdForNewQuestion.setTitle("Please wait...");
pdForNewQuestion.setMessage("Question is loading...");
pdForNewQuestion.setCancelable(false);
pdForNewQuestion.setIndeterminate(true);
pdForNewQuestion.show();
}
#Override
protected Void doInBackground(Void... arg0) {
wordsCursor = dbHelper.getRandomWords();
return null;
}
#Override
protected void onPostExecute(Void result) {
if (pdForNewQuestion != null) {
pdForNewQuestion.dismiss();
}
}
}.execute();
}
Check whether the dialog is showing or not if dialog is showing then only dismiss like this..
#Override
protected void onDestroy() {
if (pdForNewQuestion != null) {
if (pdForNewQuestion.isShowing()) {
pdForNewQuestion.dismiss();
pdForNewQuestion = null;
}
}
super.onDestroy();
}
you are running infinite loop inside new Thread but not breaking the loop and stopping that Thread. It runs infinitely in the background even when activity goes background. try stopping the Thread once work is finished.
First of all why are you starting your AsyncTask inside a Thread? As i understand you are trying to start an AsyncTask every 60 seconds and populate a new question. There is a much better way to do this using only a Handler and AsyncTask.
Create a Handler and post Runnable which runs every seconds and depending on the result start your AsyncTask :
int mSeconds = 0;
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if(mSeconds == 60){
new QuestionLoader().execute();
mSeconds = 0;
}
mHandler.postDelayed(this, 1000);
mSeconds++;
}
}, 1000);
and you can create your AsyncTask like this :
private class QuestionLoader extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute(){
super.onPreExecute();
pdForNewQuestion = new ProgressDialog(MainActivity.this);
pdForNewQuestion.setTitle("Please wait...");
pdForNewQuestion.setMessage("Question is loading...");
pdForNewQuestion.setCancelable(false);
pdForNewQuestion.setIndeterminate(true);
pdForNewQuestion.show();
}
#Override
protected Void doInBackground(Void... params) {
wordsCursor = dbHelper.getRandomWords();
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
if(pdForNewQuestion != null && pdForNewQuestion.isShowing()){
pdForNewQuestion.dismiss();
}
}
}
This is usually caused by your app trying to display a dialog using a previously-finished Activity as a context. Then check that the activity is not closed by some other apps or other triggers before showing the dialog
if (!isFinishing()) {
//showdialog here
}
Could someone show me or teach me how I can download 5 or more mp3 in a file and playing them in my app. I've searched about it but all of people how has asked this, nothing explained it well. I don't want to download only one mp3, but multiple mp3s in a file.here is main.java
public class StreamingMp3Player extends Activity implements OnClickListener, OnTouchListener, OnCompletionListener, OnBufferingUpdateListener{
private ImageButton buttonPlayPause;
private SeekBar seekBarProgress;
public EditText editTextSongURL;
private MediaPlayer mediaPlayer;
private int mediaFileLengthInMilliseconds; // this value contains the song duration in milliseconds. Look at getDuration() method in MediaPlayer class
private final Handler handler = new Handler();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
}
/** This method initialise all the views in project*/
private void initView() {
buttonPlayPause = (ImageButton)findViewById(R.id.ButtonTestPlayPause);
buttonPlayPause.setOnClickListener(this);
seekBarProgress = (SeekBar)findViewById(R.id.SeekBarTestPlay);
seekBarProgress.setMax(99); // It means 100% .0-99
seekBarProgress.setOnTouchListener(this);
editTextSongURL = (EditText)findViewById(R.id.EditTextSongURL);
editTextSongURL.setText(R.string.testsong_20_sec);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
/** Method which updates the SeekBar primary progress by current song playing position*/
private void primarySeekBarProgressUpdater() {
seekBarProgress.setProgress((int)(((float)mediaPlayer.getCurrentPosition()/mediaFileLengthInMilliseconds)*100)); // This math construction give a percentage of "was playing"/"song length"
if (mediaPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
primarySeekBarProgressUpdater();
}
};
handler.postDelayed(notification,1000);
}
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.ButtonTestPlayPause){
/** ImageButton onClick event handler. Method which start/pause mediaplayer playing */
try {
mediaPlayer.setDataSource(editTextSongURL.getText().toString()); // setup song from http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3 URL to mediaplayer data source
mediaPlayer.prepare(); // you must call this method after setup the datasource in setDataSource method. After calling prepare() the instance of MediaPlayer starts load data from URL to internal buffer.
} catch (Exception e) {
e.printStackTrace();
}
mediaFileLengthInMilliseconds = mediaPlayer.getDuration(); // gets the song length in milliseconds from URL
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
buttonPlayPause.setImageResource(R.drawable.button_pause);
}else {
mediaPlayer.pause();
buttonPlayPause.setImageResource(R.drawable.button_play);
}
primarySeekBarProgressUpdater();
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if(v.getId() == R.id.SeekBarTestPlay){
/** Seekbar onTouch event handler. Method which seeks MediaPlayer to seekBar primary progress position*/
if(mediaPlayer.isPlaying()){
SeekBar sb = (SeekBar)v;
int playPositionInMillisecconds = (mediaFileLengthInMilliseconds / 100) * sb.getProgress();
mediaPlayer.seekTo(playPositionInMillisecconds);
}
}
return false;
}
#Override
public void onCompletion(MediaPlayer mp) {
/** MediaPlayer onCompletion event handler. Method which calls then song playing is complete*/
buttonPlayPause.setImageResource(R.drawable.button_play);
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
/** Method which updates the SeekBar secondary progress by current song loading from URL position*/
seekBarProgress.setSecondaryProgress(percent);
}
You'll need to use 3rd party libraries to support MP3 playback, as it is not included in the standard library. See Wikipedia for a list of alternatives.
For the downloading part, use an URLConnection to get an InputStream on the file and write it to a FileOutputStream. This might help, too: Working unbuffered Streams