play an mp3 with MediaPlayer class on Android issues
What is wrong with my code? I have a toggle button and i would like to play/stop an mp3. I guess that the code should be as follows:
package com.android.iFocus;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ToggleButton;
public class iFocusActivity extends Activity implements OnClickListener {
public int count;
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.rain);
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ToggleButton toggleRain = (ToggleButton)findViewById(R.id.toggleRain);
//Define Listeners
toggleRain.setOnClickListener(this);
count = 0;
}
@Override
public void onClick(View toggleRain) {
if(count==0){
mediaPlayer.start();
count=1;
} else {
//MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.rain);
mediaPlayer.pause();
mediaPlayer.stop();
mediaPlayer.release();
count=0;
}
}
}
the problem is: Eclipse doesn't give any error, but on emulator/phone it gives me an exception and die immediately after started. here goes:
10-02 20:28:24.312: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.android.iFocus/.iFocusActivity }
10-02 20:28:24.392: DEBUG/AndroidRuntime(960): Shutting down VM
10-02 20:28:24.402: DEBUG/dalvikvm(960): Debugger has detached; object registry had 1 entries
10-02 20:28:24.462: INFO/ActivityManager(59): Start proc com.android.iFocus for activity com.android.iFocus/.iFocusActivity: pid=967 uid=10036 gids={}
10-02 20:28:24.502: INFO/AndroidRuntime(960): NOTE: attach of thread 'Binder Thread #3' failed
10-02 20:28:25.822: DEBUG/AndroidRuntime(967): Shutting down VM
10-02 20:28:25.822: WARN/dalvikvm(967): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
10-02 20:28:25.932: ERROR/AndroidRuntime(967): FATAL EXCEPTION: main
10-02 20:28:25.932: ERROR/AndroidRuntime(967): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.android.iFocus/com.android.iFocus.iFocusActivity}: java.lang.NullPointerException
Well, when i initialize mediaPlayer inside onClick inner class, it doesn't give me any error and the aplication doesn't give me any error for to start the song. but it does not stop as should. So, when i click on toggleButton, it starts, when i click again, it doesn't do anything but give me an error on log cat:
Error when first press toggle button and the song starts ok (but give this error):
10-02 20:39:02.712: INFO/ActivityManager(59): Start proc com.android.iFocus for activity com.android.iFocus/.iFocusActivity: pid=996 uid=10036 gids={}
10-02 20:39:02.782: INFO/AndroidRuntime(989): NOTE: attach of thread 'Binder Thread #3' failed
10-02 20:39:04.432: INFO/ActivityManager(59): Displayed activity com.android.iFocus/.iFocusActivity: 1804 ms (total 640049 ms)
10-02 20:39:08.672: DEBUG/AudioSink(34): bufferCount (4) is too small and increased to 12
10-02 20:39:08.982: WARN/AudioFlinger(34): write blocked for 73 msecs, 2105 delayed writes, thread 0xb3b8
10-02 20:39:09.682: DEBUG/d开发者_如何学Pythonalvikvm(437): GC_EXPLICIT freed 686 objects / 38192 bytes in 216ms
10-02 20:39:14.502: WARN/AudioFlinger(34): write blocked for 86 msecs, 2110 delayed writes, thread 0xb3b8
10-02 20:39:14.642: DEBUG/dalvikvm(188): GC_EXPLICIT freed 164 objects / 11408 bytes in 176ms
10-02 20:39:19.622: DEBUG/dalvikvm(261): GC_EXPLICIT freed 43 objects / 1912 bytes in 154ms
10-02 20:39:20.352: WARN/AudioFlinger(34): write blocked for 78 msecs, 2119 delayed writes, thread 0xb3b8
Error when i again press the toggleButton and the song should stop:
10-02 20:43:22.412: ERROR/MediaPlayer(1032): pause called in state 8
10-02 20:43:22.412: ERROR/MediaPlayer(1032): error (-38, 0)
10-02 20:43:22.412: ERROR/MediaPlayer(1032): stop called in state 0
10-02 20:43:22.412: ERROR/MediaPlayer(1032): error (-38, 0)
10-02 20:43:22.612: WARN/MediaPlayer(1032): mediaplayer went away with unhandled events
10-02 20:43:22.612: WARN/MediaPlayer(1032): mediaplayer went away with unhandled events
10-02 20:43:22.622: WARN/MediaPlayer(1032): mediaplayer went away with unhandled events
10-02 20:43:22.622: WARN/MediaPlayer(1032): mediaplayer went away with unhandled events
First thing first, my analysis: 1. You didn't init the MediaPlayer inside onCreate():
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.rain);
'this' <--- this thing is NULL, so you've got a NullPointerException at Runtime, first loading app timing.
2. On second click to button, you've called
mediaPlayer.release();
And next time you click, exception at MediaPlayer State
Well, the fix is pretty much simple, you need to consider best practice on Android programming:
package pete.android.study;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ToggleButton;
public class Main extends Activity implements OnClickListener {
// declare controls
public int count = 0;
MediaPlayer mediaPlayer = null;
ToggleButton toggleRain = null;
/*
* (non-Javadoc)
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
// load layout
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// load controls
toggleRain = (ToggleButton)findViewById(R.id.toggleRain);
// init player
mediaPlayer = MediaPlayer.create(this, R.raw.rain);
// set click event handler
toggleRain.setOnClickListener(this);
// init state for playing
count = 0;
}
/*
* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View toggleRain) {
if(count == 0){
mediaPlayer.start();
count = 1;
} else {
mediaPlayer.pause();
count = 0;
}
}
/*
* (non-Javadoc)
* @see android.app.Activity#onDestroy()
*/
@Override
protected void onDestroy() {
if(mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
}
Certainly it works like charm ^^! There are many ways to improve this simple app, however, I guess you can find out by looking over Android Developers' References Documentation :)
Have you tried moving the initialization inside of onCreate instead of just inside the class body? This would be the best place to do it.
If you initialize inside of onClick, the error you show is expected. This is because a new MediaPlayer instance is being created every time you click.
Your problem is with the release()
statement here:
if(count==0){
mediaPlayer.start();
count = 1;
} else {
//MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.rain);
mediaPlayer.pause();
mediaPlayer.stop();
mediaPlayer.release();
count = 0;
}
There are a few different ways you can change this, depending on your desired result. If you just want to play/pause, as you've said, then you only need to remove the stop()
and release()
calls. ESPECIALLY release()
. That call releases the audio resources back to the system, meaning you'll need to get it back into a prepared state before you can use it again.
I highly recommend reading this reference document VERY thoroughly. The MediaPlayer class is fairly complex, and it's easy and common for mistakes like this to appear when the states aren't managed properly.
精彩评论