【问题标题】:Controlling play or pause button using eventbus使用事件总线控制播放或暂停按钮
【发布时间】:2020-11-09 12:39:59
【问题描述】:

如果我们打开我们的应用程序,新闻片段就会加载,并且新闻会自动开始播放。我们正在使用 Exoplayer 播放新闻。通知由 Exoplayer 通过 PlayerNotificationManager 创建。问题是播放暂停按钮没有跟随通知。我们已经实现了事件总线,它只改变了可绘制对象。因此,如果我们单击通知上的暂停按钮,片段上的按钮会被视为已暂停,但当我们单击它时,它会用作暂停按钮(而不是用作播放按钮)。

我们打算做的是:如果通知说暂停,片段上的按钮将被暂停,然后如果我们点击它,内容将开始播放。

代码:

NewsReaderFragment.java

     public static NewsReaderFragment newInstance() {
        return new NewsReaderFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_news_reader, container, false);
        bPlay = rootView.findViewById(R.id.button_play);
        unbinder = ButterKnife.bind(this, rootView);
        NetworkInfoUtility networkInfoUtility = new NetworkInfoUtility();
        boolean net = networkInfoUtility.isNetWorkAvailableNow(getContext());
        if (!net) {
            Toast.makeText(getContext(), CHECKNET, Toast.LENGTH_LONG).show();
        }
        exoHelper = new ExoHelper(getContext(), new Player.EventListener() {
            @Override
            public void onPlayerError(ExoPlaybackException error) {
                Crashlytics.logException(error);
                Toast.makeText(getContext(), rootView.getContext().getString(R.string.server_off), Toast.LENGTH_LONG).show();
                exoHelper.ToggleButton(false);
            }
        }, bPlay, "NewsReader");

        isPlaying = true;
        setButton();
        exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));

        return rootView;
    }

    private void setButton() {
        bPlay.setOnClickListener(view -> {

            if (!isPlaying) {
                exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
            } else {
                exoHelper.stopExo();
            }

            isPlaying = !isPlaying;
        });

    } 

 @Override
    public void onStart() {
        super.onStart();

        EventBus.getDefault().register(this);
    }

    @Override
    public void onStop() {
        
        EventBus.getDefault().unregister(this);
        super.onStop();
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(ButtonEvent event)
    {

      exoHelper.ToggleButton(event.isState());

    }

Exophelper.java

    public void stopExo() {
        if (exoPlayer != null) { //if exo is running
            Log.d(TAG, "Stopping exo....");
            exoPlayer.stop();
            //playerNotificationManager.setPlayer(null);
            customPlayerNotificationManager.setPlayer(null);
            exoPlayer.release();
            exoPlayer = null;
            ToggleButton(false);

        } else {
            Log.d(TAG, "Can't stop because No exoplayer is running");
        }
    }

    public void startExo(String newUrl) {
        if (newUrl == null || newUrl.isEmpty()) {
            Log.d(TAG, "startExo: empty url");
            Toast.makeText(context, R.string.server_off, Toast.LENGTH_SHORT).show();
            ToggleButton(false); // show pause button
            return;
        }

        if (exoPlayer != null) {
            Log.d(TAG, "startExo: Exo is already running now");
            return;
        }

        iceURL = newUrl;

        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

        TrackSelection.Factory trackSelectionFactory =
                new AdaptiveTrackSelection.Factory(bandwidthMeter);
        TrackSelector defaultTrackSelector =
                new DefaultTrackSelector(trackSelectionFactory);
        DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(
                context,
                Util.getUserAgent(context, context.getApplicationInfo().name),
                defaultBandwidthMeter);

        MediaSource mediaSource = new ExtractorMediaSource(
                Uri.parse(iceURL),
                dataSourceFactory,
                extractorsFactory,
                new Handler(), error -> {
        });

        exoPlayer = ExoPlayerFactory.newSimpleInstance(context, defaultTrackSelector);

        if (eventListener != null) {
            exoPlayer.addListener(eventListener);
        }
        exoPlayer.prepare(mediaSource);
        exoPlayer.setPlayWhenReady(true);

        //EventStatus(true);
          ToggleButton(true);
        //setPlayerNotificationManager(exoPlayer);
        createCustomPlayerNotificationManger(exoPlayer);


    }

public void ToggleButton(boolean state) {
        if (state) {
            Drawable img = button.getContext().getResources().getDrawable(R.drawable.play_button);
            button.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);
            button.setText(R.string.now_playing);
        } else {
            Drawable img1 = button.getContext().getResources().getDrawable(R.drawable.pause_button);
            button.setCompoundDrawablesWithIntrinsicBounds(img1, null, null, null);
            button.setText(R.string.server_off);
        }
    }

PlayerNotificationManager.java


这是一个大文件,所以我们只在我们使用 eventbus 的地方附加接收器:

public class NotificationBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Player player = PlayerNotificationManager.this.player;
        if (player == null
                || !isNotificationStarted
                || intent.getIntExtra(EXTRA_INSTANCE_ID, instanceId) != instanceId) {
            return;
        }
        String action = intent.getAction();
        if (ACTION_PLAY.equals(action)) {
            if (player.getPlaybackState() == Player.STATE_IDLE) {
                if (playbackPreparer != null) {
                    playbackPreparer.preparePlayback();
                }
            } else if (player.getPlaybackState() == Player.STATE_ENDED) {
                controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
            }
            controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true);

            EventBus.getDefault().post(new ButtonEvent(true));
            Log.d(TAG, "ButtonEvent: True");


        } else if (ACTION_PAUSE.equals(action)) {
            controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false);

            if (player.getPlaybackState() == Player.STATE_READY)
            {
                EventBus.getDefault().post(new ButtonEvent(false));
                Log.d(TAG, "ButtonEvent: False");
            }


        } else if (ACTION_STOP.equals(action)) {
            controlDispatcher.dispatchStop(player, /* reset= */ true);
        } else if (ACTION_DISMISS.equals(action)) {
            stopNotification(/* dismissedByUser= */ true);
        } else if (action != null
                && customActionReceiver != null
                && customActions.containsKey(action)) {
            customActionReceiver.onCustomAction(player, action, intent);
        }
    }
}

ButtonEvent.java

public class ButtonEvent {

public boolean state;

public ButtonEvent(boolean state) {
    this.state = state;
}

public boolean isState() {
    return state;
}

public void setState(boolean state) {
    this.state = state;
}

}

【问题讨论】:

    标签: android android-fragments exoplayer2.x greenrobot-eventbus-3.0


    【解决方案1】:

    isPlaying 在这种情况下是否正确,执行第二次暂停?

    private void setButton() {
            bPlay.setOnClickListener(view -> {
    
                if (!isPlaying) {
                    exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
                } else {
                    exoHelper.stopExo();
                }
                isPlaying = !isPlaying;
            });
        } 
    

    是否正在播放的状态与 Fragment 而不是 ExoHelper 相关联?

    也许这可以通过使用 exoplayers 事件侦听器重新分配 isPlaying 来轻松解决...

    player.addListener(eventListener);
    
    ...
    
    @Override
    public void onIsPlayingChanged(boolean isPlaying) {
      if (isPlaying) {
          // player is playing
      } else {
          // player is paused
      }
    }
    

    更新

    或者直接查询exoplayer的状态:

    private void setButton() {
            bPlay.setOnClickListener(view -> {
                if (!isPlaying()) {
            exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
                } else {
                    exoHelper.stopExo();
                }
            });
        } 
    
    // this method might belong in ExoHelper?
    private boolean isPlaying() {
        return player.getPlaybackState() == Player.STATE_READY && player.getPlayWhenReady();
    }
    

    延伸阅读https://exoplayer.dev/listening-to-player-events.html

    【讨论】:

    • 感谢您的回答!是的,你是对的。 isPlaying 在这种情况下为真,执行第二阶段。
    • Is there a reason why the state of whether it is playing it tied to the Fragment and not ExoHelper? 我们有另一个片段,它有类似的代码。这就是我们将状态绑定到片段的原因。
    • 所以我们应该在ExoHelper 中再次分配isPlaying?我们如何在片段中检索该状态?我的意思是获得价值?如果你能解释更多,那真的很有帮助:)
    • 用监听器更新 isPlaying 变量,不要在onCreateViewbPlay.setOnClickListener 中手动进行。这样,exoplayer 可以告诉你它什么时候播放,什么时候不播放,你不需要关心自己控制那个状态。或者调用player.getPlaybackState(),它会将状态返回给你。为我的答案添加了更新。
    猜你喜欢
    • 2017-07-10
    • 1970-01-01
    • 2017-02-02
    • 2015-12-14
    • 2018-12-03
    • 2019-06-25
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    相关资源
    最近更新 更多