2025-12-16 16:00:11 +08:00
|
|
|
package com.example.livestreaming;
|
|
|
|
|
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
import androidx.media3.common.MediaItem;
|
|
|
|
|
import androidx.media3.common.PlaybackException;
|
|
|
|
|
import androidx.media3.common.Player;
|
|
|
|
|
import androidx.media3.exoplayer.ExoPlayer;
|
|
|
|
|
|
|
|
|
|
import com.example.livestreaming.databinding.ActivityPlayerBinding;
|
|
|
|
|
|
|
|
|
|
public class PlayerActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
public static final String EXTRA_PLAY_URL = "extra_play_url";
|
|
|
|
|
public static final String EXTRA_TITLE = "extra_title";
|
|
|
|
|
|
|
|
|
|
private ActivityPlayerBinding binding;
|
|
|
|
|
private ExoPlayer player;
|
|
|
|
|
private boolean triedAltUrl = false;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
binding = ActivityPlayerBinding.inflate(getLayoutInflater());
|
|
|
|
|
setContentView(binding.getRoot());
|
|
|
|
|
|
|
|
|
|
String t = getIntent().getStringExtra(EXTRA_TITLE);
|
|
|
|
|
setTitle(t != null ? t : "Live");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onStart() {
|
|
|
|
|
super.onStart();
|
|
|
|
|
String url = getIntent().getStringExtra(EXTRA_PLAY_URL);
|
|
|
|
|
if (url == null || url.trim().isEmpty()) return;
|
|
|
|
|
|
|
|
|
|
triedAltUrl = false;
|
|
|
|
|
|
2025-12-17 17:23:54 +08:00
|
|
|
// 创建低延迟播放器配置
|
|
|
|
|
ExoPlayer exo = new ExoPlayer.Builder(this)
|
|
|
|
|
.setLoadControl(new androidx.media3.exoplayer.DefaultLoadControl.Builder()
|
|
|
|
|
// 减少缓冲区大小,降低延迟
|
|
|
|
|
.setBufferDurationsMs(
|
|
|
|
|
1000, // 最小缓冲时长 1秒
|
|
|
|
|
3000, // 最大缓冲时长 3秒
|
|
|
|
|
500, // 播放缓冲时长 0.5秒
|
|
|
|
|
1000 // 播放后缓冲时长 1秒
|
|
|
|
|
)
|
|
|
|
|
.build())
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
// 设置播放器视图
|
2025-12-16 16:00:11 +08:00
|
|
|
binding.playerView.setPlayer(exo);
|
2025-12-17 17:23:54 +08:00
|
|
|
|
|
|
|
|
// 启用低延迟模式
|
|
|
|
|
binding.playerView.setUseController(true);
|
|
|
|
|
binding.playerView.setControllerAutoShow(false);
|
2025-12-16 16:00:11 +08:00
|
|
|
|
|
|
|
|
String altUrl = getAltHlsUrl(url);
|
|
|
|
|
exo.addListener(new Player.Listener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onPlayerError(PlaybackException error) {
|
|
|
|
|
if (triedAltUrl) return;
|
|
|
|
|
if (altUrl == null || altUrl.trim().isEmpty()) return;
|
|
|
|
|
triedAltUrl = true;
|
|
|
|
|
|
|
|
|
|
exo.setMediaItem(MediaItem.fromUri(altUrl));
|
|
|
|
|
exo.prepare();
|
|
|
|
|
exo.setPlayWhenReady(true);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
exo.setMediaItem(MediaItem.fromUri(url));
|
|
|
|
|
exo.prepare();
|
|
|
|
|
exo.setPlayWhenReady(true);
|
|
|
|
|
player = exo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onStop() {
|
|
|
|
|
super.onStop();
|
|
|
|
|
if (player != null) {
|
|
|
|
|
player.release();
|
|
|
|
|
player = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getAltHlsUrl(String url) {
|
|
|
|
|
if (!url.endsWith(".m3u8")) return null;
|
|
|
|
|
if (url.contains("/index.m3u8")) return null;
|
|
|
|
|
|
|
|
|
|
return url.substring(0, url.length() - ".m3u8".length()) + "/index.m3u8";
|
|
|
|
|
}
|
|
|
|
|
}
|