2017-06-17 121 views
0

嗨我正在建立一個響應原生android模塊的音樂流。當我嘗試播放音樂時,它會與我加載的第一個URL一起工作,但當我嘗試加載另一個URL時,該應用程序會崩潰。Android音樂流式播放器

下面是該模塊的代碼。

package com.mediaplayer; 

import android.media.AudioManager; 
import android.media.MediaPlayer; 
import android.os.AsyncTask; 

import com.facebook.react.bridge.ReactApplicationContext; 
import com.facebook.react.bridge.ReactContextBaseJavaModule; 
import com.facebook.react.bridge.ReactMethod; 

import java.io.IOException; 

public class MediaPlayerModule extends ReactContextBaseJavaModule { 
    String stream = "http://stream.radioreklama.bg:80/radio1rock128"; 
    boolean prepared = false; 
    boolean started = false; 

    MediaPlayer mediaPlayer; 
    PlayerTask playerTask; 

    public MediaPlayerModule(ReactApplicationContext reactContext) { 
     super(reactContext); 
     mediaPlayer = new MediaPlayer(); 
     mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
    } 

    @Override 
    public String getName() { 
     return "MediaPlayerModule"; 
    } 


    @ReactMethod 
    public void play(String url) { 
     if(prepared){ 
      mediaPlayer.reset(); 
      mediaPlayer.release(); 
     } 
     playerTask = new PlayerTask(); 
     playerTask.execute(url); 
    } 


    @ReactMethod 
    public void pause() { 

     if(mediaPlayer != null){ 
      mediaPlayer.reset(); 
      mediaPlayer.release(); 
      mediaPlayer = null; 
     } 
    } 

    @ReactMethod 
    public void resume() { 
     if (started) { 
      mediaPlayer.start(); 
     } 
    } 

    @ReactMethod 
    public void destroy() { 
     if (prepared) { 
      mediaPlayer.release(); 
      started = false; 
     } 
    } 

    class PlayerTask extends AsyncTask<String, Void, Boolean> { 
     @Override 
     protected Boolean doInBackground(String... strings) { 
      Boolean prepared = false; 

       try { 
        mediaPlayer.setDataSource(strings[0]); 
        mediaPlayer.prepare(); 
        prepared = true; 
       } catch (IOException e) { 
        e.printStackTrace(); 
        prepared = false; 
       } 

      return prepared; 
     } 

     @Override 
     protected void onPostExecute(Boolean aBoolean) { 
      super.onPostExecute(aBoolean); 
      mediaPlayer.start(); 
      started = true; 

     } 
    } 
} 

有一個頁面包含歌曲及其URL。當我在第一頁上選擇一首歌曲時,它會用歌曲的URL導航到第二頁。下面是第二頁的js代碼(播放的歌曲的頁面):

var mp = require('react-native').NativeModules.MediaPlayerModule; 

export default class Player extends Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      image: this.props.navigation.state.params.image, 
      title: this.props.navigation.state.params.title, 
      artistes: this.props.navigation.state.params.artistes, 
      mp3Url:this.props.navigation.state.params.mp3Url 
     } 
    } 

    componentDidMount(){ 
     mp.play(this.state.mp3Url); 
    } 
} 

編輯:這裏是logcat的:

--------- beginning of crash 
06-17 07:21:28.544 2406-2432/com.downstream E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3 
                   Process: com.downstream, PID: 2406 
                   java.lang.RuntimeException: An error occurred while executing doInBackground() 
                    at android.os.AsyncTask$3.done(AsyncTask.java:309) 
                    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) 
                    at java.util.concurrent.FutureTask.setException(FutureTask.java:223) 
                    at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
                    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                    at java.lang.Thread.run(Thread.java:818) 
                   Caused by: java.lang.IllegalStateException 
                    at android.media.MediaPlayer.nativeSetDataSource(Native Method) 
                    at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1085) 
                    at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1046) 
                    at com.mediaplayer.MediaPlayerModule$PlayerTask.doInBackground(MediaPlayerModule.java:118) 
                    at com.mediaplayer.MediaPlayerModule$PlayerTask.doInBackground(MediaPlayerModule.java:112) 
                    at android.os.AsyncTask$2.call(AsyncTask.java:295) 
                    at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)  
                    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)  
                    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)  
                    at java.lang.Thread.run(Thread.java:818)  
06-17 07:21:28.914 2406-2428/com.downstream E/Surface: getSlotFromBufferLocked: unknown buffer: 0xae6b5f10 

回答

1

也許當你玩第二部曲接下來的時間內崩潰,因爲,它可能會獲得Mediaplayer的「NULL」對象。請發佈您的logcat崩潰,以便我可以更確定我的答案。

+0

我已經添加了logcat的 – digiwebguy

+0

「布爾準備= FALSE; 「從「doInBackground()」中刪除這一行。媒體播放器無法重置爲「public void play(String url)」,因爲'prepare'始終保持爲「false」。刪除上面的行將直接訪問你的全球「準備」。 –

+0

謝謝。我不知道我是如何錯過的。我刪除它,但它仍然崩潰,但:/ – digiwebguy

0

@Rahul Gupta的評論讓我以正確的方式思考問題。所以問題是我在做錯誤的地方準備檢查。我所需要做的就是將if(prepared)else塊移動到我的異步任務中,並解決了問題。下面的代碼:

這就是玩兒法貌似現在:

@ReactMethod 
public void play(String url) { 
    playerTask = new PlayerTask(); 
    playerTask.execute(url); 
} 

和這裏的異步任務:

class PlayerTask extends AsyncTask<String, Void, Boolean> { 
    @Override 
    protected Boolean doInBackground(String... strings) { 

     if(prepared){ 
      mediaPlayer.reset(); 
     } 

     try { 
      mediaPlayer.setDataSource(strings[0]); 
      mediaPlayer.prepare(); 
      mediaPlayer.start(); 
      prepared = true; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      prepared = false; 
     } 

     return prepared; 
    } 

    @Override 
    protected void onPostExecute(Boolean aBoolean) { 
     super.onPostExecute(aBoolean); 

    } 
}