2016-09-23 93 views
0

我试图在后台播放音轨,以便在用户按主页按钮时继续运行。当尝试在服务后台播放声音时发生java.lang.IllegalStateException

我的方法是使用Service,因为它似乎是实现此类行为的最佳方法。

我的代码在一个活动和一个服务文件被划分:

AudioPlaybackActivity.java

//.... 
Intent serviceIntent; 
@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.audio_playback_activity); 
try 
{ 
    serviceIntent = new Intent(this, AudioPlaybackService.class); 
}catch (Exception e) 
{ 
    e.printStackTrace(); 
} 
} 

    @Override 
    public void onClick (View view) 
    { 
     switch (view.getId()) 
     { 
      // ........ 
      case R.id.play: 
      { 
       try 
       { 
       startService(serviceIntent); // Start the service when click on the play button 
       }catch(Exception e) 
       { 
        e.printStackTrace(); 
       } 
       break; 
      } 
     } 
    } 

AudioPlaybackService.java

public class AudioPlaybackService extends Service implements MediaPlayer.OnCompletionListener, 
     MediaPlayer.OnPreparedListener, 
     MediaPlayer.OnErrorListener 
{ 
    private MediaPlayer mediaPlayer; 

    @Override 
    public void onCreate() 
    { 

     mediaPlayer = new MediaPlayer(); 
     mediaPlayer.setOnPreparedListener(this); 
     mediaPlayer.setOnCompletionListener(this); 
     mediaPlayer.setOnErrorListener(this); 
     mediaPlayer.reset(); 
    } 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) 
    { 
     if (!mediaPlayer.isPlaying()) 
     { 
      mediaPlayer.reset(); 
      mediaPlayer = MediaPlayer.create(this.getApplicationContext(), R.raw.poi1); 
      mediaPlayer.prepareAsync(); 
     } 
     return START_STICKY; 
    } 
    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     if (mediaPlayer != null) 
     { 
      if (mediaPlayer.isPlaying()) 
      { 
       mediaPlayer.stop(); 
      } 
      mediaPlayer.release(); 
     } 
    } 
    @Override 
    public void onCompletion(MediaPlayer mp) 
    { 
     stopAudio(); 
     stopSelf(); // Stop the Service itself 
    } 
    @Override 
    public void onPrepared(MediaPlayer arg0) 
    { 
     playAudio(); 
    } 
    @Override 
    public boolean onError(MediaPlayer mp, int what, int extra) 
    { 
     return false; 
    } 

    @Override 
    public IBinder onBind(Intent arg0) 
    { 
     return null; 
    } 


    public void playAudio() 
    { 
     if (!mediaPlayer.isPlaying()) 
     { 
      mediaPlayer.start(); 
     } 
    } 
    public void stopAudio() 
    { 
     if(mediaPlayer.isPlaying()) 
     { 
      mediaPlayer.stop(); 
     } 
    } 

的AndroidManifest.xml file:

//......... 
<service android:name="com.medigarage.audioguide.AudioPlaybackService" 
     android:enabled="true"> 
</service> 

每当我点击播放按钮启动音频播放,应用程序崩溃。这里是回溯:

09-23 20:41:11.960 32753-32753/com.xxxxx.xxxxx E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.xxxxx.xxxxxx, PID: 32753 
    java.lang.RuntimeException: Unable to start service [email protected] with Intent { cmp=com.xxxx.xxxxxx/.AudioPlaybackService }: java.lang.IllegalStateException 
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2872) 
    at android.app.ActivityThread.access$2100(ActivityThread.java:155) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1341) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:136) 
    at android.app.ActivityThread.main(ActivityThread.java:5433) 
    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:1268) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) 
    at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.IllegalStateException 
    at android.media.MediaPlayer.prepareAsync(Native Method) 
    at com.xxxxx.xxxxxx.AudioPlaybackService.onStartCommand(AudioPlaybackService.java:35) 
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2855) 
    at android.app.ActivityThread.access$2100(ActivityThread.java:155)  
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1341)  
    at android.os.Handler.dispatchMessage(Handler.java:102)  
    at android.os.Looper.loop(Looper.java:136)  
    at android.app.ActivityThread.main(ActivityThread.java:5433)  
    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:1268)  
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)  
    at dalvik.system.NativeStart.main(Native Method)  

任何想法,为什么服务没有启动?

回答

0

你的问题是与

mediaPlayer = MediaPlayer.create(this.getApplicationContext(), R.raw.poi1); 
mediaPlayer.prepareAsync(); 

按照Android Docs for MediaPlayer.create()

Convenience method to create a MediaPlayer for a given resource id. On success, prepare() will already have been called and must not be called again.

你不应该叫mediaPlayer.prepareAsync()调用后MediaPlayer.create()

但如果你想异步准备MediaPlayer,您可以直接设置数据源而不是使用便利create()方法如下:

mediaPlayer.setDataSource(getResources().openRawResourceFd(R.raw.poi1)); 
+0

现在我得到的F继续编译错误:'无法解析方法setDataSource(android.content.res.AssetFileDescriptor' – Malloc

+0

看起来像在[API 24](https://developer.android.com/reference/android/media/MediaPlayer。html#setDataSource(android.content.res.AssetFileDescriptor)),所以相反,只需使用'getFileDescriptor()'方法将'AssetFileDescriptor'变成'FileDescriptor',就像这样'mediaPlayer.setDataSource(getResources()。openRawResourceFd(R。 raw.poi1).getFileDescriptor());' –

0

是的。您的服务实际上已经开始,但媒体播放器已经准备就绪。

当您在本地播放文件时,请勿使用mediaPlayer.prepareAsync();,像创建媒体播放器一样自动准备播放器。只要删除mediaPlayer.prepareAsync();行,它应该工作。

编辑:

你能做到像你这样做,但没有prepareAsync()行,或者像这样:

1)把你的原始音频源的位置到URI,像这样:

Uri UriOfFile = Uri.parse("android.resource://com.my.package/raw/audioFileName"); 

2),然后这个代码来播放该文件:

MediaPlayer mediaPlayer = new MediaPlayer(); 
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
mediaPlayer.setDataSource(getApplicationContext(), UriOfFile); 
mediaPlayer.prepare(); // or prepareAsync() 
mediaPlayer.start();