ExoPlayer报错'Player is accessed on wrong thread'的解决咨询
解决ExoPlayer "Player is accessed on wrong thread" 异常
问题根源
你遇到的异常是因为ExoPlayer的所有操作(包括状态查询如getCurrentPosition())必须在它绑定的线程执行。你的ExoPlayer实例绑定在ConnectivityThread中,但你直接在主线程调用getCurrentPosition(),违反了线程一致性要求,触发了ExoPlayer的线程检查机制。
解决方案
1. 统一所有ExoPlayer操作到绑定线程
确保所有对ExoPlayer的调用(包括查询位置)都通过它绑定的线程执行,再将结果回调到主线程更新UI。
示例代码(基于你的BackgroundAudioService):
// 在Service中定义线程和Handler private HandlerThread playerThread; private Handler playerHandler; private ExoPlayer exoPlayer; @Override public void onCreate() { super.onCreate(); // 初始化并启动ExoPlayer绑定的线程 playerThread = new HandlerThread("ConnectivityThread"); playerThread.start(); playerHandler = new Handler(playerThread.getLooper()); // 在绑定线程中创建ExoPlayer实例 playerHandler.post(() -> { exoPlayer = new ExoPlayer.Builder(this).build(); // 这里完成播放器的其他初始化(设置媒体源、监听等) }); } // 主线程调用此方法更新UI public void syncPlayerPositionToUi() { playerHandler.post(() -> { // 在绑定线程中安全获取位置 long currentPos = exoPlayer.getCurrentPosition(); // 切换回主线程更新UI runOnUiThread(() -> { // 执行你的UI更新逻辑,比如更新进度条 // progressBar.setProgress((int) currentPos); }); }); }
2. 用监听替代主动轮询(更优方案)
避免频繁轮询getCurrentPosition(),改用ExoPlayer的监听机制获取位置变化,既符合线程要求又更高效:
// 在绑定线程中添加监听 playerHandler.post(() -> { exoPlayer.addAnalyticsListener(new AnalyticsListener() { @Override public void onPlaybackStateChanged(@NonNull PlaybackStateChangedEvent event) { // 播放状态变化时更新位置 updatePositionUi(); } @Override public void onPositionDiscontinuity(@NonNull PositionDiscontinuityEvent event) { // 位置跳变时更新 updatePositionUi(); } }); // 若需要定期更新,可在绑定线程中启动定时任务 playerHandler.postDelayed(new Runnable() { @Override public void run() { updatePositionUi(); playerHandler.postDelayed(this, 1000); // 每秒更新一次 } }, 1000); }); // 封装位置更新逻辑 private void updatePositionUi() { long pos = exoPlayer.getCurrentPosition(); runOnUiThread(() -> { // 更新UI }); }
3. 清理资源避免线程泄漏
在Service销毁时,记得正确释放线程和ExoPlayer:
@Override public void onDestroy() { playerHandler.post(() -> { exoPlayer.release(); exoPlayer = null; }); playerThread.quitSafely(); super.onDestroy(); }
内容的提问来源于stack exchange,提问作者Alejandro Gomez
相关产品推荐
相关产品推荐

