Android音乐流式播放器
问题描述:
嗨我正在建立一个响应原生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
答
也许当你玩第二部曲接下来的时间内崩溃,因为,它可能会获得Mediaplayer的“NULL”对象。请发布您的logcat崩溃,以便我可以更确定我的答案。
答
@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);
}
}
我已经添加了logcat的 – digiwebguy
“布尔准备= FALSE; “从“doInBackground()”中删除这一行。媒体播放器无法重置为“public void play(String url)”,因为'prepare'始终保持为“false”。删除上面的行将直接访问你的全球“准备”。 –
谢谢。我不知道我是如何错过的。我删除它,但它仍然崩溃,但:/ – digiwebguy