使用Service,AsyncTask和Thread制作智能Android Media Player应用程序

首先:抱歉,如果我拼错了。 我来自巴拉圭,我正在使用谷歌翻译。

这可能看起来有点傻,而且我是一个完美主义者,就像任何优秀的开发人员和设计师一样,不要在我的项目中存在错误。 我正在学习,希望能和你学到很多东西

我见过媒体播放器应用程序允许用户快速反复按下播放/停止按钮而不会杀死应用程序,并且这仍然正常运行,所以我读到了有关ServicesAsyncTaskThread 。 不仅要在后台播放声音,还要不要因UI错误而杀死我的应用程序。 我还有很多问题。

我想知道我是否在使用以下资源( 在网上找到 )的良好路径,但我已经尝试过,当我按下播放/停止按钮几次或有时根本不播放歌曲时,应用程序会死机。

 package com.myaudioservice.app; import android.app.Service; import android.content.Intent; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.AsyncTask; import android.os.Binder; import android.os.IBinder; /** * Service to serv MediaPlayer in background * * @author Eugeny Pozharsky */ public class PlayerService extends Service { private final IBinder mBinder = new LocalBinder(); private MediaPlayer mediaPlayer; private PlayerCallback callback; public class LocalBinder extends Binder { PlayerService getService() { return PlayerService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } /** * Kill MediaPlayer to release resources */ @Override public void onDestroy() { super.onDestroy(); if (mediaPlayer != null) { stop(); mediaPlayer.release(); } } /** * Starts playing stream. * Note that we just start media player and do not obtain real URL of the stream. * So, URL that will be redirected by server will not work. To make such URLs works, adding * algorithm to obtain the real URL (fe, create HttpConnection, connect to the server and * get real URL from connection). * * @param url String with URL of a server to connect */ public void start(String url) { if (mediaPlayer == null) { mediaPlayer = new MediaPlayer(); } if (isPlaying()) { mediaPlayer.stop(); mediaPlayer.reset(); } new Player().execute(url); Log.e("PlayerService", "start()"); } /** * Stops playing of the stream. */ public void stop() { // stopping MediaPlayer in separate thread because it can take a time new Thread(new Runnable() { @Override public void run() { if (mediaPlayer != null) { if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); } //mediaPlayer.release(); //mediaPlayer = null; } } }).start(); if (callback != null) { callback.onStopped(); } Log.e("PlayerService", "stop()"); } /** * Is stream playing? * * @return true or false */ public Boolean isPlaying() { return mediaPlayer != null && mediaPlayer.isPlaying(); } public void setCallback(PlayerCallback callback) { this.callback = callback; } /** * Background task to start MediaPlayer. It is used because starting playing of remote stream may * take long time and we must not block UI thread. * Also, this approach allows to cancel starting process (not implemented in current version) */ private class Player extends AsyncTask { /** * This function called in UI thread and we callback to activity to update UI elements */ @Override protected void onPreExecute() { super.onPreExecute(); if (callback != null) { callback.onPreStart(); } } /** * This function called in UI thread and we callback to activity to update UI elements */ @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); if (mediaPlayer == null || !mediaPlayer.isPlaying()) { // Start MediaPlayer fail. if (callback != null) { callback.onStartFailed(); } } else { if (callback != null) { callback.onStarted(); } } } /** * This function called from separate thread and we do long-time operation in it * * @param strings params * @return null */ @Override protected Void doInBackground(String... strings) { //mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource(strings[0]); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.prepare(); mediaPlayer.start(); } catch (Exception e) { if (mediaPlayer != null) { mediaPlayer.release(); } mediaPlayer = null; } return null; } } } 

我想知道我是否应该在任何时候取消我的AsyncTask进程,或者我是否应该添加/修改我的应用程序不会死的东西。 我应该怎么做? 有人可以指导我吗?

我通常在我的logcast中得到错误(如果出现),如下所示:

 java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once) 

对于播放/停止按钮:

 btn_control.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { control((!ON_PLAY) ? 1 : 0); } }); private void control(int est) { if(est==1){ if (!hayConexion()) { Toast.makeText(Principal.this, getString(R.string.error_conexion_txt), Toast.LENGTH_SHORT).show(); } else { if (mBound) { mService.start(); ON_PLAY = true; } } }else if(est==0) { if (mBound) { mService.stop(); ON_PLAY = false; } } } 

编辑:

logcat的:

 09-08 03:13:08.333 32438-32474/com.myaudioservice.app V/MediaPlayer-JNI﹕ native_setup 09-08 03:13:08.333 32438-32474/com.myaudioservice.app V/MediaPlayer﹕ constructor 09-08 03:13:08.343 32438-32474/com.myaudioservice.app V/MediaPlayer﹕ setListener 09-08 03:13:08.343 32438-32474/com.myaudioservice.app I/MediaPlayer﹕ path is null 09-08 03:13:08.343 32438-32474/com.myaudioservice.app D/MediaPlayer﹕ setDataSource IOException happend : java.io.FileNotFoundException: No content provider: rtsp://ip/folder/file.stream at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1053) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:907) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:834) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:988) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:942) at com.myaudioservice.app.PlayerService$Player.doInBackground(PlayerService.java:156) at com.myaudioservice.app.PlayerService$Player.doInBackground(PlayerService.java:130) at android.os.AsyncTask$2.call(AsyncTask.java:288) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:841) 09-08 03:13:08.343 32438-32474/com.myaudioservice.app D/MediaPlayer﹕ Couldn't open file on client side, trying server side 09-08 03:13:08.353 32438-32474/com.myaudioservice.app V/MediaPlayer-JNI﹕ setAudioStreamType: 3 09-08 03:13:08.353 32438-32474/com.myaudioservice.app V/MediaPlayer﹕ MediaPlayer::setAudioStreamType 09-08 03:13:08.353 32438-32474/com.myaudioservice.app D/com.myaudioservice.app.PlayerService﹕ Preparing: rtsp://ip/folder/file.stream 09-08 03:13:08.353 32438-32474/com.myaudioservice.app V/MediaPlayer﹕ setVideoSurfaceTexture 09-08 03:13:08.353 32438-32474/com.myaudioservice.app V/MediaPlayer﹕ prepare 09-08 03:13:09.384 32438-32438/com.myaudioservice.app E/PlayerService﹕ stop() 09-08 03:13:09.394 32438-32495/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 03:13:09.394 32438-32495/com.myaudioservice.app V/MediaPlayer-JNI﹕ release 09-08 03:13:09.394 32438-32495/com.myaudioservice.app V/MediaPlayer﹕ setListener 09-08 03:13:09.394 32438-32495/com.myaudioservice.app V/MediaPlayer﹕ disconnect 09-08 03:13:09.544 32438-32438/com.myaudioservice.app D/AndroidRuntime﹕ Shutting down VM 09-08 03:13:09.544 32438-32438/com.myaudioservice.app W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x4193eda0) 09-08 03:13:09.544 32438-32438/com.myaudioservice.app E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.myaudioservice.app, PID: 32438 java.lang.IllegalStateException at android.media.MediaPlayer.isPlaying(Native Method) at com.myaudioservice.app.PlayerService.reproduciendo(PlayerService.java:118) at com.myaudioservice.app.PlayerService.start(PlayerService.java:84) at com.myaudioservice.app.MainActivity.control(MainActivity.java:298) at com.myaudioservice.app.MainActivity.access$100(MainActivity.java:38) at com.myaudioservice.app.MainActivity$1.onClick(MainActivity.java:173) at android.view.View.performClick(View.java:4640) at android.view.View$PerformClick.run(View.java:19425) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:146) at android.app.ActivityThread.main(ActivityThread.java:5593) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099) at dalvik.system.NativeStart.main(Native Method) 

新LOGCAT:

  09-08 14:49:24.360 9651-9651/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 14:49:24.360 9651-9651/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 14:49:24.390 9651-9651/com.myaudioservice.app E/PlayerService﹕ start() 09-08 14:49:24.480 9651-10534/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 14:49:24.480 9651-10534/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 14:49:24.480 9651-10534/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 14:49:24.480 9651-10534/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 14:49:24.490 9651-9651/com.myaudioservice.app E/PlayerService﹕ stop() 09-08 14:49:24.620 9651-9651/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 14:49:24.620 9651-9651/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 14:49:24.650 9651-9651/com.myaudioservice.app E/PlayerService﹕ start() 09-08 14:49:24.770 9651-10535/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 14:49:24.770 9651-10535/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 14:49:24.770 9651-10535/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 14:49:24.770 9651-10535/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 14:49:24.780 9651-9651/com.myaudioservice.app E/PlayerService﹕ stop() 09-08 14:49:24.890 9651-9651/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 14:49:24.890 9651-9651/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 14:49:24.910 9651-9651/com.myaudioservice.app E/PlayerService﹕ start() 09-08 14:49:25.021 9651-10540/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 14:49:25.031 9651-10540/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 14:49:25.031 9651-10540/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 14:49:25.031 9651-10540/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 14:49:25.041 9651-9651/com.myaudioservice.app E/PlayerService﹕ stop() 09-08 14:49:25.151 9651-9651/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 14:49:25.151 9651-9651/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 14:49:25.181 9651-9651/com.myaudioservice.app E/PlayerService﹕ start() 

编辑2:———————————————– ————————

我以为我已经拥有它,直到我得到一个错误(就在我的服务结束时):(

编辑过的PlayerService类

 package com.myaudioservice.app; import android.app.Service; import android.content.Intent; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class PlayerService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnInfoListener, MediaPlayer.OnCompletionListener { private static final String LOG_TAG = PlayerService.class.getName(); private String URL_STREAM = "rtsp://domain/folder/file.stream"; private MediaPlayer mMediaPlayer = null; private PlayerCallback callback; private final IBinder mBinder = new LocalBinder(); public class LocalBinder extends Binder { PlayerService getService() { return PlayerService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onDestroy(){ if (mMediaPlayer != null) { stop(); mMediaPlayer.release(); mMediaPlayer = null; } } /** * Starts playing stream. * Note that we just start media player and do not obtain real URL of the stream. * So, URL that will be redirected by server will not work. To make such URLs works, adding * algorithm to obtain the real URL (fe, create HttpConnection, connect to the server and * get real URL from connection). * * //@param url String with URL of a server to connect */ public void start() { if (mMediaPlayer == null) mMediaPlayer = new MediaPlayer(); if (isPlaying()) { mMediaPlayer.stop(); mMediaPlayer.reset(); } try { mMediaPlayer.setDataSource(URL_STREAM); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); if (callback != null) callback.onPreStart(); Log.e(LOG_TAG, "Preparando: " + URL_STREAM); mMediaPlayer.prepareAsync(); } catch (Exception e) { if (mMediaPlayer != null) { mMediaPlayer.reset(); } Log.e(LOG_TAG, e.toString()); //mMediaPlayer = null; } mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.setOnInfoListener(this); mMediaPlayer.setOnCompletionListener(this); } @Override public void onPrepared(MediaPlayer mp) { mp.start(); Log.e(LOG_TAG, "start()"); } @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { switch (what) { case MediaPlayer.MEDIA_ERROR_IO: case MediaPlayer.MEDIA_ERROR_MALFORMED: case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: case MediaPlayer.MEDIA_ERROR_SERVER_DIED: case MediaPlayer.MEDIA_ERROR_TIMED_OUT: case MediaPlayer.MEDIA_ERROR_UNSUPPORTED: if (mMediaPlayer == null || !mMediaPlayer.isPlaying()) { // Start MediaPlayer fail. if (callback != null) callback.onStartFailed(); } Log.e(LOG_TAG, "Error"); break; case MediaPlayer.MEDIA_INFO_BUFFERING_START: if (callback != null) callback.onStarted(); Log.e(LOG_TAG, "Almacenando en búfer"); break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: if (callback != null) callback.onPlaying(); Log.e(LOG_TAG, "Reproduciendo"); break; } return false; } @Override public void onCompletion(MediaPlayer mp) { Log.e(LOG_TAG, "Reproducción finalizada"); stop(); } /** * Stops playing of the stream. */ public void stop() { // stopping MediaPlayer in separate thread because it can take a time new Thread(new Runnable() { @Override public void run() { if (mMediaPlayer != null) { if (mMediaPlayer.isPlaying()) mMediaPlayer.stop(); // I get the error here when I destroy the Service quickly mMediaPlayer.reset(); } } }).start(); if (callback != null) callback.onStopped(); Log.e(LOG_TAG, "stop()"); } /** * Is stream playing? * * @return true or false */ public Boolean isPlaying() { return mMediaPlayer != null && mMediaPlayer.isPlaying(); } public void setCallback(PlayerCallback callback) { this.callback = callback; } } 

logcat的:

 09-08 19:15:39.578 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 19:15:39.578 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:39.578 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ setAudioStreamType: 3 09-08 19:15:39.578 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ MediaPlayer::setAudioStreamType 09-08 19:15:39.578 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ Preparando: rtsp://domain/folder/file.stream 09-08 19:15:39.578 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ setVideoSurfaceTexture 09-08 19:15:39.578 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ prepareAsync 09-08 19:15:39.678 27582-31945/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:39.678 27582-31945/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 19:15:39.678 27582-31945/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 19:15:39.678 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=1, ext1=0, ext2=0 09-08 19:15:39.688 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(1, 0, 0) callback on disconnected mediaplayer 09-08 19:15:39.688 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=8, ext1=0, ext2=0 09-08 19:15:39.688 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(8, 0, 0) callback on disconnected mediaplayer 09-08 19:15:39.688 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ stop() 09-08 19:15:39.798 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 19:15:39.798 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:39.808 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ setAudioStreamType: 3 09-08 19:15:39.808 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ MediaPlayer::setAudioStreamType 09-08 19:15:39.808 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ Preparando: rtsp://domain/folder/file.stream 09-08 19:15:39.808 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ setVideoSurfaceTexture 09-08 19:15:39.808 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ prepareAsync 09-08 19:15:39.938 27582-31952/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:39.938 27582-31952/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 19:15:39.938 27582-31952/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 19:15:39.938 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=1, ext1=0, ext2=0 09-08 19:15:39.938 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(1, 0, 0) callback on disconnected mediaplayer 09-08 19:15:39.938 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=8, ext1=0, ext2=0 09-08 19:15:39.938 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(8, 0, 0) callback on disconnected mediaplayer 09-08 19:15:39.948 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ stop() 09-08 19:15:40.069 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 19:15:40.069 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:40.079 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ setAudioStreamType: 3 09-08 19:15:40.079 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ MediaPlayer::setAudioStreamType 09-08 19:15:40.079 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ Preparando: rtsp://domain/folder/file.stream 09-08 19:15:40.079 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ setVideoSurfaceTexture 09-08 19:15:40.079 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ prepareAsync 09-08 19:15:40.179 27582-31957/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:40.179 27582-31957/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 19:15:40.179 27582-31957/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 19:15:40.179 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=1, ext1=0, ext2=0 09-08 19:15:40.189 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(1, 0, 0) callback on disconnected mediaplayer 09-08 19:15:40.189 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=8, ext1=0, ext2=0 09-08 19:15:40.189 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(8, 0, 0) callback on disconnected mediaplayer 09-08 19:15:40.189 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ stop() 09-08 19:15:40.289 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 19:15:40.289 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:40.299 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ setAudioStreamType: 3 09-08 19:15:40.299 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ MediaPlayer::setAudioStreamType 09-08 19:15:40.299 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ Preparando: rtsp://domain/folder/file.stream 09-08 19:15:40.299 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ setVideoSurfaceTexture 09-08 19:15:40.299 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ prepareAsync 09-08 19:15:40.429 27582-31966/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:40.429 27582-31966/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 19:15:40.429 27582-31966/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 19:15:40.429 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=1, ext1=0, ext2=0 09-08 19:15:40.429 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(1, 0, 0) callback on disconnected mediaplayer 09-08 19:15:40.429 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ stop() 09-08 19:15:40.429 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=8, ext1=0, ext2=0 09-08 19:15:40.429 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(8, 0, 0) callback on disconnected mediaplayer 09-08 19:15:40.549 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ isPlaying: no active player 09-08 19:15:40.549 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:40.559 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ setAudioStreamType: 3 09-08 19:15:40.559 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ MediaPlayer::setAudioStreamType 09-08 19:15:40.559 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ Preparando: rtsp://domain/folder/file.stream 09-08 19:15:40.559 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ setVideoSurfaceTexture 09-08 19:15:40.559 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ prepareAsync 09-08 19:15:40.659 27582-31972/com.myaudioservice.app V/MediaPlayer-JNI﹕ isPlaying: 0 09-08 19:15:40.659 27582-31972/com.myaudioservice.app V/MediaPlayer-JNI﹕ reset 09-08 19:15:40.659 27582-31972/com.myaudioservice.app V/MediaPlayer﹕ reset 09-08 19:15:40.659 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=1, ext1=0, ext2=0 09-08 19:15:40.659 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(1, 0, 0) callback on disconnected mediaplayer 09-08 19:15:40.659 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ message received msg=8, ext1=0, ext2=0 09-08 19:15:40.659 27582-27596/com.myaudioservice.app V/MediaPlayer﹕ notify(8, 0, 0) callback on disconnected mediaplayer 09-08 19:15:40.669 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ stop() 09-08 19:16:01.281 27582-27582/com.myaudioservice.app D/AbsListView﹕ onDetachedFromWindow 09-08 19:16:01.311 27582-27582/com.myaudioservice.app E/com.myaudioservice.app.PlayerService﹕ stop() 09-08 19:16:01.311 27582-27582/com.myaudioservice.app V/MediaPlayer-JNI﹕ release 09-08 19:16:01.311 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ setListener 09-08 19:16:01.311 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ disconnect 09-08 19:16:01.311 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ destructor 09-08 19:16:01.311 27582-32148/com.myaudioservice.app W/dalvikvm﹕ threadid=14: thread exiting with uncaught exception (group=0x4193eda0) 09-08 19:16:01.311 27582-27582/com.myaudioservice.app V/MediaPlayer﹕ disconnect 09-08 19:16:01.321 27582-32148/com.myaudioservice.app E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-15992 Process: com.myaudioservice.app, PID: 27582 java.lang.IllegalStateException at android.media.MediaPlayer.isPlaying(Native Method) at com.myaudioservice.app.PlayerService$1.run(PlayerService.java:129) at java.lang.Thread.run(Thread.java:841) 

在文档中,您可以读到如果内部播放器引擎尚未初始化或已被释放, MediaPlayer.isPlaying()将抛出IllegalStateException。

这段代码不是线程安全的,这可能是这个exception的原因(线程调用release()并且在发布的mediaPlayer上将mediaPlayer设置为null app调用isPlaying() )。 您需要添加一些同步才能使其工作(或使用MediaPlayer异步方法)。

好吧,我想我终于得到了我想要的东西。 我不知道我是否应该将@KamilW响应标记为正确,因为它确实是正确的,但我会用正确的代码回答我的问题(或者至少认为是对的)它对其他人有用。

我的最终代码:

 package com.myaudioservice.app; import android.app.Service; import android.content.Intent; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class PlayerService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnInfoListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener { private static final String LOG_TAG = PlayerService.class.getName(); private String URL_STREAM = "rtsp://domain/folder/file.stream"; private MediaPlayer mMediaPlayer = null; private PlayerCallback callback; private final IBinder mBinder = new LocalBinder(); public class LocalBinder extends Binder { PlayerService getService() { return PlayerService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onDestroy(){ if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; } } /** * Starts playing stream. * Note that we just start media player and do not obtain real URL of the stream. * So, URL that will be redirected by server will not work. To make such URLs works, adding * algorithm to obtain the real URL (fe, create HttpConnection, connect to the server and * get real URL from connection). * * //@param url String with URL of a server to connect */ public void start() { if (mMediaPlayer == null) mMediaPlayer = new MediaPlayer(); if (isPlaying()) { mMediaPlayer.stop(); mMediaPlayer.reset(); } try { mMediaPlayer.setDataSource(URL_STREAM); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); if (callback != null) callback.onPreStart(); Log.e(LOG_TAG, "Preparando: " + URL_STREAM); mMediaPlayer.prepareAsync(); } catch (Exception e) { if (mMediaPlayer != null) { mMediaPlayer.reset(); } if (callback != null) callback.onStartFailed(); Log.e(LOG_TAG, e.toString()); //mMediaPlayer = null; } mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.setOnInfoListener(this); mMediaPlayer.setOnErrorListener(this); mMediaPlayer.setOnCompletionListener(this); } @Override public void onPrepared(MediaPlayer mp) { mp.start(); Log.e(LOG_TAG, "start()"); } @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { switch (what) { case MediaPlayer.MEDIA_INFO_BUFFERING_START: if (callback != null) callback.onStarted(); Log.e(LOG_TAG, "Almacenando en búfer"); break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: if (callback != null) callback.onPlaying(); Log.e(LOG_TAG, "Reproduciendo"); break; } return false; } @Override public void onCompletion(MediaPlayer mp) { Log.e(LOG_TAG, "Reproducción finalizada"); stop(); } /** * Stops playing of the stream. */ public void stop() { // stopping MediaPlayer in separate thread because it can take a time new Thread(new Runnable() { @Override public void run() { if (mMediaPlayer != null) { if (mMediaPlayer.isPlaying()) mMediaPlayer.stop(); mMediaPlayer.reset(); } } }).start(); if (callback != null) callback.onStopped(); Log.e(LOG_TAG, "stop()"); } /** * Is stream playing? * * @return true or false */ public Boolean isPlaying() { return mMediaPlayer != null && mMediaPlayer.isPlaying(); } public void setCallback(PlayerCallback callback) { this.callback = callback; } @Override public boolean onError(MediaPlayer mp, int what, int extra){ if(what == MediaPlayer.MEDIA_ERROR_UNKNOWN || what == MediaPlayer.MEDIA_ERROR_SERVER_DIED || extra == MediaPlayer.MEDIA_ERROR_IO || extra == MediaPlayer.MEDIA_ERROR_MALFORMED || extra == MediaPlayer.MEDIA_ERROR_UNSUPPORTED || extra == MediaPlayer.MEDIA_ERROR_TIMED_OUT || extra == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK){ stop(); if (callback != null) callback.onStartFailed(); } return true;// Si hay error, no es necesario llamar a onCompletionListener, por eso: true } } 

我还想接受专家的检查,告诉我在代码中需要改进的地方(如果不是太多要问的话)。 Thak You。