I'm trying to get music to play on my app but I've hit a problem which I can't figure out. When I first load the program, it works fine and the music loads and plays. If I let the phone idle and then come back to it, the app works again. But the third time I let it idle and return, the mediaplayer will return a null and crash the app on resuming. Here is the code for the mediaplayer:
public void startMusic(Context context)
{
if (music != null){
if (music.isPlaying()){
music.stop();
}
music.release();
music = null;
}
music = MediaPlayer.create(context, R.raw.song);
music.setLooping(true);
musicPlaying = true;
}
The app will crash when it hits the music.setLooping(true); line of code, saying that music is null.
Any ideas?
It turns out I was releasing the music in the wrong place. I was doing it in the view, when I should have been doing it in the activity.
Related
There'd be a button on the home screen which would play a certain song and change the background image of the button. If the user clicks on the button again (when the music is playing) then the music should stop and the background image of the button should set itself back to the general position. But it looks like the program can't detect if my Mediaplayer is playing. What am I missing here?
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
AppWidgetManager appWidgetManager= AppWidgetManager.getInstance(context);
RemoteViews rv= new RemoteViews(context.getPackageName(),
R.layout.playbtn_widget);
if (intent.getAction().equals("btnPlay")) {
if (!mediaPlayer.isPlaying()) {
mediaPlayer= MediaPlayer.create(context,R.raw.itsmylife);
mediaPlayer.start();
rv.setImageViewResource(R.id.imbtnwidget,
R.drawable.btnk32);
} else {
mediaPlayer.stop();
}
mediaPlayer.setOnCompletionListener(mediaPlayer -> {
rv.setImageViewResource(R.id.imbtnwidget,
R.drawable.btnk3);
appWidgetManager.updateAppWidget(new ComponentName(context,
BtnAppWidgetProvider.class), rv);
});
appWidgetManager.updateAppWidget(new ComponentName(context,
BtnAppWidgetProvider.class), rv);
}
}
It should set the background image back and stop the music when I tap on the button, but it just starts the mediaplayer again and the background image remains the same. I have no idea how I could fix this. It seems like it creates a new mediaplayer every single time
Issue
It creates a new Media Player because the class is recreated or re-executed. This clears all the variables and re-defines them. This makes the issue in your case.
Solution
Just create a class name anything like MediaPlayerHelper.java
Create a variable of MediaPlayer which is public and static. Like this:
public static MediaPlayer mp;
Now, when the button is pressed, you can check if it is playing or not. Something like this:
if(MediaPlayerHelper.mp != null && MediaPlayerHelper.mp.isPlaying()){
// the media player is currently playing. Stop it.
}else{
// the media is not playing. Start it
}
I am doing a little trivia game that plays a correct or wrong song when the user chooses an answer. This is my function:
public void playSound(boolean isRight) {
if(isRight){
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.correct);
mp.setVolume(VOLUME,VOLUME);
mp.start();
}else{
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.wrong);
mp.setVolume(VOLUME,VOLUME);
mp.start();
}
}
My problem is that even though my audio is properly played, it has an extremly low volume on my device(which has maximun volume).
I already tried many solutions found here on Stackoverflow but the only one that seems to work is this: Android MediaPlayer not playing sound on some devices but it doesnt respect the user's volume.
Any ideas?
I have a few media players setup to play one after another on a button click however there is a noticeable gap between the media players playing ie. once mediaplayer one has finished there is a half a second before mediaplayer two plays, for the purpose I'm using the mediaplayers for the gap in audio is very noticeable, so what I'm asking is, is there a way to remove this gap. Now I don't know if I'm going wrong using different mediaplayers each time however this is what I've come up with so far.
Basically I've got onCompleteionListeners for each mediaplayer and within those I have the next mediaplayer play until the last. Any pointers would be appreciated.
public void onClick(View v) {
mpButtonThree = MediaPlayer.create(MainActivity.this, R.raw.audioReplay);
if (mpButtonThree==null){
//display a Toast message here
return;
}
mpButtonThree.start();
mpButtonThree.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mpButtonThree) {
mpButtonThree.release();
mpButtonOne = MediaPlayer.create(MainActivity.this, audioReplayPrimary);
if (mpButtonOne==null){
//display a Toast message here
return;
}
mpButtonOne.start();
mpButtonOne.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mpButtonOne) {
mpButtonOne.release();
mpButtonTwo = MediaPlayer.create(MainActivity.this, audioReplaySecondary);
if (mpButtonTwo==null){
//display a Toast message here
return;
}
mpButtonTwo.start();
mpButtonTwo.setOnCompletionListener(new soundListener1()
{
});
}
If You play files in series you can use single media player object.
create function that plays next media file and put it into OnCompletion.
This should remove gap between playing, because You don't have to release and create media player every time
I have an app uploaded on google play. This is the link.
It hasn't been tested on many devices yet so errors are pretty common. A user messaged me today saying that the app crashes if the togglebutton is turned ON and the button is only pressed, not held.
This is the logcat file that he sent me:
E/MessageQueue-JNI(31135): java.lang.RuntimeException: stop failed.
E/MessageQueue-JNI(31135): at android.media.MediaRecorder.stop(Native Method)
E/MessageQueue-JNI(31135): at com.whizzappseasyvoicenotepad.MainActivity.stopRecording(MainActivity.java:183)
Quote:
App doesn't always crash. Sometimes it does, sometimes it doesn't. It only happens when the togglebutton is ON. If I touch and hold the button it works fine but if I only touch it for a moment it crashes. I'm using Xperia S 4.1.2
I tried this on my phone, I only touched the button instead of holding it and it worked perfectly fine, I don't know why this is happening on his phone.
This is the code for onTouchListener:
recBtn.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
startRecording();
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
stopRecording();
nameAlert();
}
return true;
}
});
And the logcat says the problem occurs when stopRecording is called, so here is the stopRecording method:
public void stopRecording() {
final ImageButton recBtn = (ImageButton) findViewById(com.whizzappseasyvoicenotepad.R.id.recButton);
final ToggleButton tBtn = (ToggleButton) findViewById(R.id.tBtn1);
if (null != recorder) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
recBtn.setImageResource(com.whizzappseasyvoicenotepad.R.drawable.record_btn);
stopTimer();
tBtn.setEnabled(true);
}
}
I'm guessing that the problem is that he only touches the button for a moment, so before startRecording is completely called, the stopRecoring is already called so it crashes because startRecording wasn't even completely intiated yet. If that's the case, how can I fix it? If it isn't the case, what's wrong then? And why would an error like this appear on another phone but not mine?
According to documentation, this is the normal behavior:
public void stop ()
Added in API level 1 Stops recording. Call this after start(). Once
recording is stopped, you will have to configure it again as if it has
just been constructed. Note that a RuntimeException is intentionally
thrown to the application, if no valid audio/video data has been
received when stop() is called. This happens if stop() is called
immediately after start(). The failure lets the application take
action accordingly to clean up the output file (delete the output
file, for instance), since the output file is not properly constructed
when this happens.
So you can just add a try catch to your stop call
if (null != recorder) {
try{
recorder.stop();
}catch(RuntimeException ex){
//Ignore
}
...
}
I have written the following code for playing video:
private void loadPlayer() {
Intent youtube=new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.youtube.com/watch?v=CES7xNy70hU"));
startActivityForResult(youtube, 100);
}
My problem is that when the player finishes showing the video it won't close itself and the user needs to press the back button. I need the player to close itself automatically after the video has finished playing. How can I accomplish this?
The target platform is Android - 2.2.
Create an activity that just displays a VideoViewer. Play the video from there. Implement a listener for the completion of the video. Then call finish within there to end the activity:
videoViewer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp)
{
finish();
}
});
This will return you to the previous Activity.