我正在做一个广播应用程序(喜欢收听)
情况:
- 当 radio 首先启动时,它会播放音频广告,然后启动 radio (广告和 radio 是 2 个不同的流)
- 当 AACPlayer 当前正在播放音乐并且用户更改电台时
两个问题:
- 当广告结束时,AACPlayer 需要停止并从另一个 URL 开始
- 当用户选择另一个 radio 时是一样的
AACDecoder 库只有两种方法 - 开始() - 停止()
这些方法会相互干扰并使播放器处于不确定状态
我用这段代码启动了一个播放器:
public void start(String url) throws Exception {
if (mPlayer == null) {
mPlayer = new MultiPlayer(this);
}
mPlayer.playAsync(url);
mState = StreamingState.PREPARING;
}
然后像这样停止它:
public void stop() {
if (mPlayer == null) {
return;
}
try {
mPlayer.stop();
mPlayer = null;
} catch (Exception e) {
}
setState(StreamingState.STOPPING);
}
我使用这个回调接口(interface):
static interface RadioPlayerCallBack {
public void radioPlayerStarted();
public void radioPlayerStopped(int perf);
public void radioPlayerException(Throwable e);
public void radioPlayerMetadata(String key, String value);
public void radioPlayerPCMFeedBuffer(boolean isPlaying, int audioBufferSizeMs, int audioBufferCapacityMs);
}
我用这个枚举更新播放器的状态:
public enum StreamingState {
EMPTY, // media player rested or releasedS
CREATED, // created ready to prepare
PREPARING, // preparing...
PREPARED, // prepared
STARTED, // started, and maybe playing (ready to play)
PAUSED, // paused (media player ready!)
STOPPED, // stopped and not prepared to play
ERROR, // an error occured, mediaplayer is reseted
STOPPING, // startAsync after stop
}
我找不到在已经播放流的播放器上执行 Stop() -> start(url) 的解决方案,同时确保状态播放器(我必须考虑网络的延迟)
我怎样才能做到这一点?
编辑
这是如何完成的快速 View :
[PlayerActivity -> StreamingService -> PlayerObject]
顺序:
单击按钮播放 -> 通过从 serviceConnection 获取的实例从 StreamingService 调用方法 playRadio -> 从 PlayerObject 调用方法播放 -> playerState=starting -> 方法 playerStarted 自动调用 -> playerState=started -> 从 StreamingService 的回调方法-> 广播一个 Intent 通知 UI -> ui 获取 Intent 并更新界面...
这是广播接收器:
final private BroadcastReceiver mPlayBackReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String actionString = intent.getAction();
if (actionString == ServiceStreaming.SERVICE_PLAY) {
} else if (actionString == ServiceStreaming.SERVICE_STOP) {
} else if (actionString == ServiceStreaming.SERVICE_LOADING) {
} else if (actionString == ServiceStreaming.SERVICE_ERROR) {
} else if (actionString == ServiceStreaming.SERVICE_KILLED) {
}
}
};
有时我得到这个异常:
06-04 10:15:43.531: E/AudioTrack(8218): AudioFlinger could not create track, status: -12
06-04 10:15:43.531: E/AudioTrack-JNI(8218): Error initializing AudioTrack
06-04 10:15:43.531: E/android.media.AudioTrack(8218): Error code -20 when initializing AudioTrack.
06-04 10:15:43.531: E/PCMFeed(8218): error in playback feed: -3
06-04 10:15:43.541: E/BufferReader(8218): Exception when reading: java.net.SocketException: Socket closed
06-04 10:15:43.901: A/libc(8218): Fatal signal 11 (SIGSEGV) at 0x76652748 (code=1), thread 8955 (Thread-5266)
06-04 10:15:43.911: E/AACPlayer(8218): playAsync():
06-04 10:15:43.911: E/AACPlayer(8218): java.lang.IllegalStateException
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.Decoder.start(Decoder.java:231)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer.playImpl(AACPlayer.java:424)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer.play(AACPlayer.java:386)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer.play(AACPlayer.java:338)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer$1.run(AACPlayer.java:296)
06-04 10:15:43.911: E/AACPlayer(8218): at java.lang.Thread.run(Thread.java:841)
最佳答案
我认为应该通过回调函数来完成 playercallback 接口(interface)可以在这里找到:
AACPlayer本身的功能是:
/**
* Sets the PlayerCallback.
* NOTE: this should be set BEFORE any of the play methods are called.
*/
public void setPlayerCallback( PlayerCallback playerCallback )
然后当播放器停止时执行此函数:
/**
* This method is called when the player is stopped.
* Note: __after__ this method the method playerException might be also called.
*/
public void playerStopped( int perf );
只需将您的重启逻辑放入此函数即可。
链接到 aacPlayer 的来源:
编辑 1
有一个链接到使用 aacPlayer 的 Activity 源: https://code.google.com/p/aacplayer-android/source/browse/trunk/src/com/spoledge/aacplayer/AACPlayerActivity.java
你应该注意到在回调函数中使用了一个处理程序并且代码在单独的线程中执行而不是在玩家线程中执行:
public void playerStopped( final int perf ) {
uiHandler.post( new Runnable() {
public void run() {
enableButtons();
...
playerStarted = false;
}
});
}
有时我得到这个异常:
06-04 10:15:43.531: E/AudioTrack(8218): AudioFlinger could not create track, status: -12
06-04 10:15:43.531: E/AudioTrack-JNI(8218): Error initializing AudioTrack
06-04 10:15:43.531: E/android.media.AudioTrack(8218): Error code -20 when initializing AudioTrack.
06-04 10:15:43.531: E/PCMFeed(8218): error in playback feed: -3
06-04 10:15:43.541: E/BufferReader(8218): Exception when reading: java.net.SocketException: Socket closed
06-04 10:15:43.901: A/libc(8218): Fatal signal 11 (SIGSEGV) at 0x76652748 (code=1), thread 8955 (Thread-5266)
06-04 10:15:43.911: E/AACPlayer(8218): playAsync():
06-04 10:15:43.911: E/AACPlayer(8218): java.lang.IllegalStateException
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.Decoder.start(Decoder.java:231)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer.playImpl(AACPlayer.java:424)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer.play(AACPlayer.java:386)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer.play(AACPlayer.java:338)
06-04 10:15:43.911: E/AACPlayer(8218): at com.spoledge.aacdecoder.AACPlayer$1.run(AACPlayer.java:296)
06-04 10:15:43.911: E/AACPlayer(8218): at java.lang.Thread.run(Thread.java:841)
编辑2
类似问题的链接:
Android Application crashes after generating an audio signal a few times
关于java - 使用 AACDecoder 开始新流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24694868/