I followed a youtube tutorial that showed how to create an android mp3 player app. The App has multiple buttons, one for previous song, one for Pause/Play and one for next song. Play/Pause buttons, only pause my MediaPlayer and they work perfectly no matter how many times i click them.
On the other hand, Next/Previous buttons causes my code to throw NullPointerException. I found out it was because MediaPlayer.create(Context, Uri) function sometimes returns null. On my app, function fails approx. on every tenth press of Next button, or on every tenth creation of MediaPlayer.
Is there a way to fix this? I tried modifying application on my own, but it didn't work. I tried looping variable myMysicPlayer in continue while loop, until it gets while != null
while(myMusicPlayer != null){
Uri u = new Uri(...);
myMediaPlayer = MediaPlayer.create(getAppContext(), u);
}
I tried using a listener that waits till myMusicPlayer was ready to be stopped, but it was just dereferencing null, and that failed obviosely.
btnNext.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMediaPlayer.stop();
myMediaPlayer.reset();
myMediaPlayer.release();
position = (position + 1) % mySongs.size();
Uri u = Uri.parse(mySongs.get(position).toString());
songLabelName.setText(mySongs.get(position).toString());
myMediaPlayer = MediaPlayer.create(getApplicationContext(), u);
myMediaPlayer.start();
}
});
The error message:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.aizenangel.myapplication, PID: 20169
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.start()' on a null object reference at com.aizenangel.myapplication.SongPlayer$4.onClick(SongPlayer.java:168)
at android.view.View.performClick(View.java:6291)
at android.view.View$PerformClick.run(View.java:24931)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
I/Process: Sending signal. PID: 20169 SIG: 9
My mistake was:
1) i used myMediaPlayer.release() method, that releases all resources
associated with the MediaPlayer object
2) instead of using the same MediaPlayer object, i always create new one with myMediaPlayer = MediaPlayer.create(Context, Uri), and
MediaPlayer.create(Context, Uri) returns null on failure, which than causes NullPointerException.
Solution was simple. I deleted myMediaPlayer.release() line and instead of creating new object, i modified the one whose reference i got in the begining.
btnNext.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMediaPlayer.stop();
myMediaPlayer.reset();
position = (position+1)%mySongs.size();
Uri u = Uri.parse((mySongs.get(position)).toString());
songLabelName.setText(mySongs.get(position).toString());
try {
myMediaPlayer.setDataSource(getApplicationContext(),u);
myMediaPlayer.prepare();
}catch (IOException e) {
e.printStackTrace();
}
myMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
myMediaPlayer.start();
}
});
}
});
Related
Im streaming an mp3 audio from a url by using mediaplayer, Now im able to play music , But when i press back button or close the app, it crashes.
can anyone pls help me to find my mistake.
thank you.
My code is :
private ImageView play, forward, backward;
private MediaPlayer mediaPlayer;
private boolean playing = false;
private ProgressDialog dialog;
private String mp3link;
private SeekBar seekbar;
private Handler handler = new Handler();
private int mediaPos;
private int mediaMax;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String url ="";
initWidgets();
}
private void initWidgets() {
mp3link = "http://loc8app.com/church/uploads/audio/749928ad6fcb7b1aceefdf03bd7a9465.mp3";
play = (ImageView) findViewById(R.id.control);
seekbar = (SeekBar) findViewById(R.id.seekBar);
// forward = (ImageView) findViewById(R.id.playeer_forward);
// backward = (ImageView) findViewById(R.id.playeer_back);
mediaPlayer = new MediaPlayer();
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
playFunction();
}
});
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mediaPlayer != null && fromUser){
mediaPlayer.seekTo(progress);
}
}
});
}
private void playFunction() {
if (!playing) {
try {
dialog = ProgressDialog
.show(MainActivity.this,
"",
getString(com.root5solutions.music.R.string.buffering),
true);
dialog.setCancelable(true);
dialog.show();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(mp3link);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
play.setBackgroundResource(R.drawable.pause);
playing = true;
//this is new
mediaPos = mp.getCurrentPosition();
mediaMax = mp.getDuration();
seekbar.setMax(mediaMax);
seekbar.setProgress(mediaPos);
//this line is the error
handler.removeCallbacks(moveSeekBarThread);
handler.postDelayed(moveSeekBarThread, 100);
mp.start();
dialog.dismiss();
}
});
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
dialog.dismiss();
}
} else {
play.setBackgroundResource(R.drawable.play);
mediaPlayer.stop();
mediaPlayer.release();
playing = false;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
private Runnable moveSeekBarThread = new Runnable() {
public void run() {
if (mediaPlayer.isPlaying()) {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekbar.setMax(mediaMax_new);
seekbar.setProgress(mediaPos_new);
handler.postDelayed(this, 1000); // Looping the thread after 1 second
}
}
};
}
Logcat shows :
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.root.music, PID: 26981
java.lang.IllegalStateException
at android.media.MediaPlayer.isPlaying(Native Method)
at com.root.music.MainActivity$4.run(MainActivity.java:132)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5351)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:947)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:742)
The issue appears to be being caused by the moveSeekBarThread Runnable, from which the exception is being raised, continuing to execute after mediaPlayer is released in onBackPressed(). This results in the the isPlaying() method being executed, which as per the documentation will result in an IllegalStateException:
if the internal player engine has not been initialized or has been released.
Looking at moveSeekBarThread, it seems to be configured to reschedule itself endlessly by posting itself back into the handler Handler instance with a delay. This process is not being stopped when the user leaves the activity, which explains why moveSeekBarThread keeps running. So, based on the above, one solution could be to make sure that any instances of moveSeekBarThread in handler's queue are removed before calling mediaPlayer.release() when the user leaves the activity.
You should be able to do that by calling handler.removeCallbacks(moveSeekBarThread); before you call mediaPlayer.release(). For example, as follows:
#Override
public void onBackPressed() {
super.onBackPressed();
handler.removeCallbacks(moveSeekBarThread);
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
It should be okay to call it right before mediaPlayer.release(), but I think it's safer to call it regardless of whether mediaPlayer is playing. This way, if the Runnable does get or remain started somehow despite the media player not having being started or having been stopped, the Runnable will still be cleared.
As an aside, while I don't have any experience with MediaPlayer, I happened to notice that the documentation of the release method has the following to say:
It is considered good practice to call this method when you're done using the MediaPlayer. In particular, whenever an Activity of an application is paused (its onPause() method is called), or stopped (its onStop() method is called), this method should be invoked to release the MediaPlayer object, unless the application has a special need to keep the object around. In addition to unnecessary resources (such as memory and instances of codecs) being held, failure to call this method immediately if a MediaPlayer object is no longer needed may also lead to continuous battery consumption for mobile devices, and playback failure for other applications if no multiple instances of the same codec are supported on a device.
So unless there is that special need to keep the media player around in the activity in your case, it might be better to handle the release process (including clearing moveSeekBarThread from handler) in onPause or onStop instead.
Hope that helps!
you are getting IllegalStateException .
Signals that a method has been invoked at an illegal or inappropriate
time .
Call super.onBackPressed(); after if condition
#Override
public void onBackPressed()
{
if (mediaPlayer!= null)
{
if(mediaPlayer.isPlaying())
mediaPlayer.stop();
mediaPlayer.release();
}
super.onBackPressed(); // Call here
}
First you need to understand what illegalStateException means:
According to Android docs:
It Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.
have a look at the state diagram of a media player:
https://developer.android.com/images/mediaplayer_state_diagram.gif
Calling setDataSource(FileDescriptor), or setDataSource(String), or setDataSource(Context, Uri), or setDataSource(FileDescriptor, long, long), or setDataSource(MediaDataSource) transfers a MediaPlayer object in the Idle state to the Initialized state.
An IllegalStateException is thrown if setDataSource() is called in any other state.
It is good programming practice to always look out for IllegalArgumentException and IOException that may be thrown from the overloaded setDataSource methods.
//playSound method and use it everywhere
public void playSound1() {
mp = MediaPlayer.create(getBaseContext(), (R.raw.clave_pop)); //sound file clave_pop in mp4 format firstly it is in m4a format then produced same problem then i use mp3 file
if (sec_sound && mp != null) //shared preference of sec_sound
mp.start();
if (vibration)//also vibrate if shared preference of vibrator is true
v.vibrate(700); //vibrate device
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
// and i am also used this but the same problem is occurred
public void playSound1() {
final MediaPlayer mp = MediaPlayer.create(Anulom_Activity.this, R.raw.clave_pop); //sound file clave_pop in mp4 format firstly it is in m4a format then produced same problem then i use mp3 file
if (sec_sound && mp != null) //shared preference of sec_sound
mp.start();
if (vibration) //also vibrate if shared preference of vibrator is true
v.vibrate(700); //device vibrate
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
// but it shows
/* java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.setOnCompletionListener(android.media.MediaPlayer$OnCompletionListener)' on a null object reference
at com.pixelpoint.Anulom_Activity.playSound1(Anulom_Activity.java:727)
at com.pixelpoint.Anulom_Activity$5$1$1.run(Anulom_Activity.java:325)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5910)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200) */
MediaPlayer create (Context context,Uri uri)
Convenience method to create a MediaPlayer for a given Uri. On success, prepare() will already have been called and must not be
called again.
When done with the MediaPlayer, you should call release(), to free the resources. If not released, too many MediaPlayer instances will
result in an exception.
Note that since prepare() is called automatically in this method, you cannot change the audio stream type (see setAudioStreamType(int)),
audio session ID (see setAudioSessionId(int)) or audio attributes (see
setAudioAttributes(AudioAttributes) of the new MediaPlayer.
Parameters
context Context: the Context to use
uri Uri: the Uri from which to get the datasource
Returns
MediaPlayer a MediaPlayer object, or null if creation failed
deselectTrack
prepare ()
Prepares the player for
playback, synchronously. After setting the datasource and the display
surface, you need to either call prepare() or prepareAsync(). For
files, it is OK to call prepare(), which blocks until MediaPlayer is
ready for playback.
as per above documentation you need call prepare or prepare async and set Onpreparelistener. Wait for call back and then call mp.start or set Oncompletion listener.
I'm using an Android MediaPlayer instance which is simple initialized by:
mediaPlayer = MediaPlayer.create(this,R.raw.conrnfield);
I also got this Thread updating a SeekBar according to the track playing progress.
updateTime = new Runnable() {
#Override
public void run() {
int currentPosition = 0;
int total = mediaPlayer.getDuration();
seekBar.setMax(total);
while (mediaPlayer != null && currentPosition < total) {
try {
Thread.sleep(500);
currentPosition = mediaPlayer.getCurrentPosition();
}
catch (InterruptedException ex) {return;}
catch (Exception e) {return;}
seekBar.setProgress(currentPosition);
}
}
};
I got a method to change the current track:
public void changeSong(View view) {
mediaPlayer.reset();
mediaPlayer.start();
mediaPlayer.selectTrack(2);
}
However, when I invoke this method, it causes the app to crash. I can see first at the log a
java.lang.IllegalStateException: Could not execute method of the activity
error message at the stacktrace.
I can't even know if my approach is wrong. This is whole log
You should use MediaPlayer.setDataSource after a call to MediaPlayer.reset. Note that the MediaPlayer.create methods are just helper methods that call MediaPlayer.setDataSource, and are suppose to be used to play one off media. In the example following context is your Activity so you could probably replace them with MainActivity.this.
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(context.getPackageName())
.appendPath(String.valueOf(R.raw.conrnfield))
.build();
mediaPlayer.setDataSource(context, uri);
I am not really sure if the error is because of I have an alarm or while loop:
MediaPlayer mpChange;
MediaPlayer saved;
mpChange = MediaPlayer.create(this, R.raw.change);
saved = MediaPlayer.create(this, R.raw.saved);
When I add a user I call a function and inside I informed the user message has saved by:
saved.start();
After that I check if user has special meaning or not and again inform the user if it does not:
else
{
/*Implement Audio Change*/
while(saved.isPlaying() == true)
{
//Nothing except wait
System.out.println("looop");
}
//saved.stop();
System.out.println("finished");
mpChange.start();
}
Code is working fine and I don't get any error or conflict between the voices. However, I get an error with in my application which says:
Application is not responding. Would you like to close?
I was not sure if it is the while loop or MediaPlayer.
Last output was:
looop
looop
looop
looop
finished
Thanks in advance for any help.
saved.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mpChange.start();
}
});
try this code in else part remove while loop
I have created a simple Ukulele tuner (The market I think lacks a visually pleasing and extremely simple tuner).
Any how, firstly, through the developer console I can see that there is a Null Pointer Exception at the Button Onclick Events. I have not been able to recreate this, however it has been reported four times.
Secondly, looking at the log while using the app I can see this warning;
E/MP3Extractor(68): Unable to resync. Signalling end of stream.
This entry here MediaPlayer array causing null pointer in Android seems to be along the same lines.
How it works.
Through the use of radio buttons the user selects either to play a single note or a continuous note. I have created a subroutine called StopMediaPlayer that stops, resets and instantiates the MediaPlayers again. This was used because I could never seem to stop the continuous play back but only pause it.
Is the warning and the NullPointerException related? Is there a more efficient/better means of stopping MediaPlayer that will mean that I wont have to re instantiate the notes every time.
Thank You
One of the offending Onclicks
Button gButton = (Button) findViewById(R.id.gButton);
gButton.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
if (singleRadio.isChecked() == true)
{
StopMediaPLayer();
gNote.setLooping(false);
gNote.start();
}
else if (contRadio.isChecked() == true)
{
StopMediaPLayer();
gNote.setLooping(true);
gNote.start();
}
}
});
Stop Media Player Subroutine
public void StopMediaPLayer()
{
Log.i("UkuleleTuner", "Stop Media Player");
gNote.setLooping(false);
cNote.setLooping(false);
eNote.setLooping(false);
aNote.setLooping(false);
gNote.stop();
cNote.stop();
eNote.stop();
aNote.stop();
gNote.reset();
cNote.reset();
eNote.reset();
aNote.reset();
gNote = MediaPlayer.create(this, R.raw.g_note);
cNote = MediaPlayer.create(this, R.raw.c_note);
eNote = MediaPlayer.create(this, R.raw.e_note);
aNote = MediaPlayer.create(this, R.raw.a_note);
}