logo
当前页

PK 连麦

功能简介

PK 连麦,指两个直播间进行主播连麦 PK 互动,应用于秀场、游戏、电商等直播场景,可以提升直播间内容的丰富性、吸引更多的粉丝流,提升直播间的娱乐气氛。

前提条件

在开始之前,请确保您完成了以下步骤:

实现流程

主播在自己的直播间开始后,可以向他们想要连接的主播发送 PK 连麦请求,一旦对方主播接受了 PK 连麦请求,两个直播间即可被连接。

开始 PK 连麦

要开始 PK 连麦,您需要调用 ZegoLiveStreamingManager.getInstance().sendPKBattleRequest(anotherHostUserID); 方法先发送一个 PK 连麦请求。一旦对方主播接受了您的请求,PK 连麦就会开始。

ZegoLiveStreamingManager.getInstance().sendPKBattleRequest(targetUserID, new UserRequestCallback() {
  @Override
  public void onUserRequestSend(int errorCode, String requestID) {
      if (errorCode != 0) {
        showTopTips(getContext().getString(R.string.livestreaming_send_pk_error, errorCode),false);
      }
      updateUI();
  }
});

停止 PK 连麦

如需停止 PK 连麦,可调用 ZegoLiveStreamingManager.getInstance().stopPKBattle(); 方法。

监听 PK 连麦事件

如需监听 PK 连麦事件,可调用 ZegoLiveStreamingManager.getInstance().addLiveStreamingListener(); 方法。
当您收到 PK 请求时,您可以为用户显示一个弹出窗口,让用户选择是否接受或拒绝。

  • 如果接受,可调用 ZegoLiveStreamingManager.getInstance().acceptIncomingPKBattleRequest();
  • 如果拒绝,可调用 ZegoLiveStreamingManager.getInstance().rejectPKBattleStartRequest();

您还可以自定义自己的业务逻辑,来处理相应的 PK 事件。

ZegoLiveStreamingManager.getInstance().addLiveStreamingListener(new ZegoLiveStreamingListener() {
  @Override
  public void onIncomingPKBattleRequestReceived(String requestID, ZegoUIKitUser anotherHostUser, String anotherHostLiveID,String customData) {
        if (startPKDialog != null && startPKDialog.isShowing()) {
            return;
        }
        AlertDialog.Builder startPKBuilder = new AlertDialog.Builder(LiveActivity.this);
        //...
        startPKDialog = startPKBuilder.create();
        startPKDialog.setCanceledOnTouchOutside(false);
        startPKDialog.show();
  }
});

示例源代码

请点击 这里,获取详细的示例源码。


根据需要自定义您自己的 PK 连麦逻辑和流程ZegoLiveStreamingManager 包含一系列方法供您进行进一步的定制。在您进行定制之前,请先阅读下方 API 简介

API 简介

发送 PK 连麦请求

public void sendPKBattleRequest(String anotherHostUserID,int timeout,String customData, UserRequestCallback callback) 
  • anotherHostUserID: 发送 PK 连麦请求时,您需要指定您想要连接的主播的用户 ID。
  • timeout: 这设置您发送的 PK 连麦请求的超时时长。超时后,发送请求的主播将通过 ZegoLiveStreamingListener.onOutgoingPKBattleRequestTimeout 接收到回调通知。
  • customData: 自定义您希望被邀请的主播接收的信息,被邀请的主播将通过 ZegoLiveStreamingListener.onIncomingPKBattleRequestReceived 接收到您设置的信息。
注意

您邀请的主播必须已经开始了直播,否则,相关错误将通过您调用的方法返回。有关错误信息和原因,请在 callback 中检查。

示例代码
ZegoLiveStreamingManager.getInstance().sendPKBattleRequest(targetUserID, new UserRequestCallback() {
  @Override
  public void onUserRequestSend(int errorCode, String requestID) {
      if (errorCode != 0) {
        showTopTips(getContext().getString(R.string.livestreaming_send_pk_error, errorCode),false);
      }
      updateUI();
  }
});

取消 PK 连麦请求

ZegoLiveStreamingManager.getInstance().cancelPKBattleRequest(String customData,UserRequestCallback callback);

当请求未超时且未收到任何响应时,可以通过调用此方法取消 PK 连麦请求。取消后,被邀请的主播将通过 ZegoLiveStreamingListener.onIncomingPKBattleRequestCancelled 接收到回调通知。

示例代码
ZegoLiveStreamingManager.getInstance().cancelPKBattleRequest(new UserRequestCallback() {
  @Override
  public void onUserRequestSend(int errorCode, String requestID) {
      updateUI();
  }
});

响应 PK 连麦请求

如需接收 PK 连麦请求,您可以 监听并设置 ZegoLiveStreamingListener.onIncomingPKBattleRequestReceived

接受 PK 连麦请求

要接受 PK 连麦请求,调用 acceptIncomingPKBattleRequest 方法。对方主播将通过 onOutgoingPKBattleRequestAccepted 接收到通知,更多细节可以在 PK请求被接受 中查看。

ZegoLiveStreamingManager.getInstance().acceptIncomingPKBattleRequest(requestID, anotherHostLiveID, anotherHostUser);

拒绝 PK 连麦请求

要拒绝 PK 连麦请求,调用 rejectIncomingPKBattleRequest 方法。对方主播将通过 onOutgoingPKBattleRequestRejected 接收到通知,并且可以通过 rejectCode 告知为什么请求被拒绝。更多细节可以在 PK 请求被拒绝 中查看。

ZegoLiveStreamingManager.getInstance().rejectPKBattleStartRequest(requestID);

响应 PK 请求的示例代码

@Override
public void onIncomingPKBattleRequestReceived(String requestID, ZegoUIKitUser anotherHostUser,
    String anotherHostLiveID, String customData) {
    if (startPKDialog != null && startPKDialog.isShowing()) {
        return;
    }
    AlertDialog.Builder startPKBuilder = new AlertDialog.Builder(LiveActivity.this);
    startPKBuilder.setTitle(
        getString(com.zegocloud.uikit.prebuilt.livestreaming.R.string.livestreaming_invite_pk_title,
            anotherHostUser.userName));
    startPKBuilder.setPositiveButton(com.zegocloud.uikit.prebuilt.livestreaming.R.string.livestreaming_ok,
        new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                ZegoLiveStreamingManager.getInstance()
                    .acceptIncomingPKBattleRequest(requestID, anotherHostLiveID, anotherHostUser);
            }
        });
    startPKBuilder.setNegativeButton(
        com.zegocloud.uikit.prebuilt.livestreaming.R.string.livestreaming_disagree, new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                ZegoLiveStreamingManager.getInstance().rejectPKBattleStartRequest(requestID);
            }
        });
    startPKDialog = startPKBuilder.create();
    startPKDialog.setCanceledOnTouchOutside(false);
    startPKDialog.show();
}

监听已发送的 PK 连麦请求

PK 连麦请求被接受

当发送的 PK 连麦请求被接受时,您可以通过监听或设置 ZegoLiveStreamingListener.onOutgoingPKBattleRequestAccepted 来接收回调通知或自定义您的业务逻辑。

  @Override
  public void onOutgoingPKBattleRequestAccepted(String anotherHostLiveID, ZegoUIKitUser anotherHostUser) {
    ZegoLiveStreamingManager.getInstance().startPKBattleWith(anotherHostLiveID, anotherHostUser.userID, anotherHostUser.userName);
  }

PK 连麦请求被拒绝

当发送的 PK 连麦请求被拒绝时,您可以通过监听或设置 ZegoLiveStreamingListener.onOutgoingPKBattleRequestRejected 来接收回调通知或自定义您的业务逻辑。

说明

当被邀请的主播处于忙碌状态时,PK 连麦请求将被自动拒绝。
忙碌状态:主播尚未启动他的直播间、主播正在与他人进行 PK 连麦、主播正在被邀请、主播正在向他人发送 PK 连麦请求。

@Override
public void onOutgoingPKBattleRequestRejected(int reason,ZegoUIKitUser anotherHostUser) {
    updateUI();
    if (reason == ZegoLiveStreamingPKBattleRejectCode.HOST_REJECT.ordinal()) {
        ZegoLiveStreamingManager.getInstance()
            .showTopTips(getContext().getString(R.string.livestreaming_send_pk_rejected), false);
    }else {
        ZegoLiveStreamingManager.getInstance()
            .showTopTips(getContext().getString(R.string.livestreaming_send_pk_busy), false);
    }
}

其中,ZegoLiveStreamingPKBattleRejectCode 可用于声明被邀请的主播为何拒绝您的请求,定义如下:

public enum ZegoLiveStreamingPKBattleRejectCode {
    HOST_REJECT, USER_NOT_HOST, IN_PK, LIVE_NOT_STARTED, ALREADY_SEND, ALREADY_RECEIVED
}

PK 连麦请求超时

如果被邀请的主播在超时时长之后没有响应,则 PK 连麦请求将默认超时。互动直播 UIKit 会更新内部状态,但不会触发任何默认行为。 您可以通过监听或设置 ZegoLiveStreamingListener.onOutgoingPKBattleRequestTimeout 来接收回调通知或自定义您的业务逻辑。

示例代码
@Override
public void onOutgoingPKBattleRequestTimeout(String requestID, ZegoUIKitUser anotherHost) {
    updateUI();
    ZegoLiveStreamingManager.getInstance()
        .showTopTips(getContext().getString(R.string.livestreaming_send_pk_no_reply), false);
}

发送 PK 连麦请求失败

在某些情况下,PK 连麦请求可能无法成功发送,例如,主播的应用程序尚未启动。 当 PK 连麦请求发送失败时,sendPKBattleRequest 会返回错误,您可以通过 sendPKBattleRequest 返回的值来识别和处理这些错误。

示例代码
ZegoLiveStreamingManager.getInstance().sendPKBattleRequest(editText.getText().toString(), new UserRequestCallback() {
  @Override
  public void onUserRequestSend(int errorCode, String requestID) {
      if (errorCode != 0) {
          ZegoLiveStreamingManager.getInstance().showTopTips(
              getContext().getString(R.string.livestreaming_send_pk_error, errorCode),
              false);
      }
      updateUI();
  }
});

监听接收到的 PK 连麦请求

接收到 PK 连麦请求

当接收到 PK 连麦请求时,您可以通过监听或设置 ZegoLiveStreamingListener.onIncomingPKBattleRequestReceived 来接收回调通知或自定义您的业务逻辑。

示例代码
 ZegoLiveStreamingManager.getInstance().addLiveStreamingListener(new ZegoLiveStreamingListener() {
  @Override
  public void onIncomingPKBattleRequestReceived(String requestID, ZegoUIKitUser anotherHostUser, String anotherHostLiveID,String customData) {
        if (startPKDialog != null && startPKDialog.isShowing()) {
            return;
        }
        AlertDialog.Builder startPKBuilder = new AlertDialog.Builder(LiveActivity.this);
        //...
        startPKDialog = startPKBuilder.create();
        startPKDialog.setCanceledOnTouchOutside(false);
        startPKDialog.show();
  }
});

接收到的 PK 连麦请求已被取消

当 PK 连麦请求被取消时,您可以通过监听或设置 ZegoLiveStreamingListener.onIncomingPKBattleRequestCancelled 来接收回调通知或自定义您的业务逻辑。

@Override
public void onIncomingPKBattleRequestCancelled(String requestID, ZegoUIKitUser anotherHostUser, String customData) {
    if (startPKDialog != null && startPKDialog.isShowing()) {
        startPKDialog.dismiss();
    }
}

接收到的 PK 连麦请求已超时

当接收到的 PK 连麦请求超时时,您可以通过监听或设置 ZegoLiveStreamingListener.onIncomingPKBattleRequestTimeout 来接收回调通知或自定义您的业务逻辑。

示例代码
@Override
public void onIncomingPKBattleRequestTimeout(String requestID, ZegoUIKitUser anotherHost) {
    if (startPKDialog != null && startPKDialog.isShowing()) {
        startPKDialog.dismiss();
    }
}

PK 连麦期间静音对方主播

当 PK 连麦开始时,两位主播都可根据需要在连麦期间静音已连接的主播。对方主播被静音后,观众就听不到被静音直播间的声音了。

ZegoLiveStreamingManager.getInstance().muteAnotherHostAudio(boolean mute,ZegoUIKitCallback callback)

您还可以通过 ZegoLiveStreamingManager().getInstance().isAnotherHostMuted() 获取对方主播的静音状态。

示例代码
boolean pkUserMuted = ZegoLiveStreamingManager.getInstance().isAnotherHostMuted();
ZegoLiveStreamingManager.getInstance().muteAnotherHostAudio(!pkUserMuted, new ZegoUIKitCallback() {
    @Override
    public void onResult(int errorCode) {
        updateButton();
    }
});

自定义预构建 UI

仅适用于 PK 连麦特性的可定制方法

除了上述用于自定义的方法外,ZegoUIKitPrebuiltLiveStreamingConfig 中的 ZegoLiveStreamingPKBattleConfig 提供了一些仅适用于 PK 连麦特性的UI和功能的定制。

class ZegoLiveStreamingPKBattleConfig {

  /// 当连接的主播因异常下线时,SDK 默认显示"Host is reconnecting"。
  /// 要自定义连接的主播下线时显示的内容,请使用 [hostReconnectingProvider]。
  public ZegoLiveStreamingPKBattleViewProvider2 hostReconnectingProvider;

  /// 要在 PKBattleView 上覆盖自定义组件,请使用 [pkBattleViewForegroundProvider]。  
   public ZegoLiveStreamingPKBattleViewProvider pkBattleViewForegroundProvider;

  /// 要在 PKBattleView 顶部添加自定义组件,请使用 [pkBattleViewTopProvider]. 
  public ZegoLiveStreamingPKBattleViewProvider pkBattleViewTopProvider;

  /// 要在 PKBattleView 底部添加自定义组件,请使用 [pkBattleViewBottomProvider]. 
  public ZegoLiveStreamingPKBattleViewProvider pkBattleViewBottomProvider;
}

其中,ZegoLiveStreamingPKBattleViewProviderZegoLiveStreamingPKBattleViewBuilder 的定义如下:

public interface ZegoLiveStreamingPKBattleViewProvider {

    View getView(ViewGroup parent, List<ZegoUIKitUser> uiKitUsers);
}

public interface ZegoLiveStreamingPKBattleViewProvider2 {

    View getView(ViewGroup parent, ZegoUIKitUser uiKitUsers);
}

如果您想将自定义视图放置在PK视图的上方、下方和顶部,可以参考以下示例代码:

// ZegoUIKitPrebuiltLiveStreamingConfig
  config.pkBattleConfig.pkBattleViewBottomProvider = new ZegoLiveStreamingPKBattleViewProvider() {
      @Override
      public View getView(ViewGroup parent, List<ZegoUIKitUser> uiKitUsers) {
          View view = new View(parent.getContext());
          view.setBackgroundColor(Color.RED);
          DisplayMetrics displayMetrics = parent.getContext().getResources().getDisplayMetrics();
          view.setLayoutParams(new FrameLayout.LayoutParams(-1, Utils.dp2px(24, displayMetrics)));
          return view;
      }
  };
  config.pkBattleConfig.pkBattleViewTopProvider = new ZegoLiveStreamingPKBattleViewProvider() {
      @Override
      public View getView(ViewGroup parent, List<ZegoUIKitUser> uiKitUsers) {
          View view = new View(parent.getContext());
          view.setBackgroundColor(Color.RED);
          DisplayMetrics displayMetrics = parent.getContext().getResources().getDisplayMetrics();
          view.setLayoutParams(new FrameLayout.LayoutParams(-1, Utils.dp2px(24, displayMetrics)));
          return view;
      }
  };
  config.pkBattleConfig.pkBattleViewForegroundProvider = new ZegoLiveStreamingPKBattleViewProvider() {
      @Override
      public View getView(ViewGroup parent, List<ZegoUIKitUser> uiKitUsers) {
          View view = new View(parent.getContext());
          view.setBackgroundColor(Color.RED);
          DisplayMetrics displayMetrics = parent.getContext().getResources().getDisplayMetrics();
          FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-1, Utils.dp2px(24, displayMetrics));
          params.topMargin = parent.getHeight() / 2;
          view.setLayoutParams(params);
          return view;
      }
  };
  config.pkBattleConfig.hostReconnectingProvider = new ZegoLiveStreamingPKBattleViewProvider2() {
      @Override
      public View getView(ViewGroup parent, ZegoUIKitUser uiKitUsers) {
          TextView textView = new TextView(LiveActivity.this);
          textView.setLayoutParams(new FrameLayout.LayoutParams(-1, -1));
          textView.setBackgroundColor(ContextCompat.getColor(LiveActivity.this,
              com.zegocloud.uikit.prebuilt.livestreaming.R.color.gray_444));
          textView.setGravity(Gravity.CENTER);
          textView.setTextColor(Color.WHITE);
          textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
          textView.setText("uiKitUsers:" + uiKitUsers.userName + " disconnected");
          return textView;
      }
  };

效果将如下所示:

示例源码

// LiveActivity.java
private void addFragment() {
    long appID = ;
    String appSign = ;
    String userID = ;
    String userName = ;

    boolean isHost = ;
    String liveID = ;

    ZegoUIKitPrebuiltLiveStreamingConfig config;
    if (isHost) {
        config = ZegoUIKitPrebuiltLiveStreamingConfig.host(true);
    } else {
        config = ZegoUIKitPrebuiltLiveStreamingConfig.audience(true);
    }

    customPKView(config);

    ZegoUIKitPrebuiltLiveStreamingFragment fragment = ZegoUIKitPrebuiltLiveStreamingFragment.newInstance(appID,
        appSign, userID, userName, liveID, config);
    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commitNow();

    addPKButton(fragment);

    addPKDialog();
}

 private void customPKView(ZegoUIKitPrebuiltLiveStreamingConfig config) {
    config.pkBattleConfig.pkBattleViewBottomProvider = new ZegoLiveStreamingPKBattleViewProvider() {
        @Override
        public View getView(ViewGroup parent, List<ZegoUIKitUser> uiKitUsers) {
            View view = new View(parent.getContext());
            view.setBackgroundColor(Color.MAGENTA);
            DisplayMetrics displayMetrics = parent.getContext().getResources().getDisplayMetrics();
            view.setLayoutParams(new FrameLayout.LayoutParams(-1, Utils.dp2px(32, displayMetrics)));
            return view;
        }
    };
    config.pkBattleConfig.pkBattleViewTopProvider = new ZegoLiveStreamingPKBattleViewProvider() {
        @Override
        public View getView(ViewGroup parent, List<ZegoUIKitUser> uiKitUsers) {
            View view = new View(parent.getContext());
            view.setBackgroundColor(Color.TRANSPARENT);
            DisplayMetrics displayMetrics = parent.getContext().getResources().getDisplayMetrics();
            view.setLayoutParams(new FrameLayout.LayoutParams(-1, Utils.dp2px(48, displayMetrics)));
            return view;
        }
    };
    config.pkBattleConfig.pkBattleViewForegroundProvider = new ZegoLiveStreamingPKBattleViewProvider() {
        @Override
        public View getView(ViewGroup parent, List<ZegoUIKitUser> uiKitUsers) {
            MutePKUserButton mutePKUserButton = new MutePKUserButton(parent.getContext());
            int size = Utils.dp2px(36f, getResources().getDisplayMetrics());
            int marginTop = Utils.dp2px(10f, getResources().getDisplayMetrics());
            int marginBottom = Utils.dp2px(16f, getResources().getDisplayMetrics());
            int marginEnd = Utils.dp2px(8, getResources().getDisplayMetrics());
            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT, size);
            layoutParams.leftMargin = parent.getWidth() / 2;
            layoutParams.topMargin = marginTop;
            layoutParams.bottomMargin = marginBottom;
            layoutParams.rightMargin = marginEnd;
            mutePKUserButton.setLayoutParams(layoutParams);
            return mutePKUserButton;
        }
    };

    config.pkBattleConfig.hostReconnectingProvider = new ZegoLiveStreamingPKBattleViewProvider2() {
        @Override
        public View getView(ViewGroup parent, ZegoUIKitUser uiKitUsers) {
            TextView textView = new TextView(LiveActivity.this);
            textView.setLayoutParams(new FrameLayout.LayoutParams(-1, -1));
            textView.setBackgroundColor(ContextCompat.getColor(LiveActivity.this,
                com.zegocloud.uikit.prebuilt.livestreaming.R.color.gray_444));
            textView.setGravity(Gravity.CENTER);
            textView.setTextColor(Color.WHITE);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
            textView.setText("uiKitUsers:" + uiKitUsers.userName + " disconnected");
            return textView;
        }
    };
}

private void addPKDialog() {
    ZegoLiveStreamingManager.getInstance().addLiveStreamingListener(new ZegoLiveStreamingListener() {
        @Override
        public void onIncomingPKBattleRequestReceived(String requestID, ZegoUIKitUser anotherHostUser,
            String anotherHostLiveID, String customData) {
            if (startPKDialog != null && startPKDialog.isShowing()) {
                return;
            }
            AlertDialog.Builder startPKBuilder = new AlertDialog.Builder(LiveActivity.this);
            startPKBuilder.setTitle(
                getString(R.string.livestreaming_invite_pk_title,
                    anotherHostUser.userName));
            startPKBuilder.setPositiveButton(com.zegocloud.uikit.prebuilt.livestreaming.R.string.livestreaming_ok,
                new OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        ZegoLiveStreamingManager.getInstance()
                            .acceptIncomingPKBattleRequest(requestID, anotherHostLiveID, anotherHostUser);
                    }
                });
            startPKBuilder.setNegativeButton(
                com.zegocloud.uikit.prebuilt.livestreaming.R.string.livestreaming_disagree, new OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        ZegoLiveStreamingManager.getInstance().rejectPKBattleStartRequest(requestID);
                    }
                });
            startPKDialog = startPKBuilder.create();
            startPKDialog.setCanceledOnTouchOutside(false);
            startPKDialog.show();
        }

        @Override
        public void onIncomingPKBattleRequestTimeout(String requestID, ZegoUIKitUser anotherHostUser) {
            if (startPKDialog != null && startPKDialog.isShowing()) {
                startPKDialog.dismiss();
            }
        }

        @Override
        public void onIncomingPKBattleRequestCanceled(String requestID, ZegoUIKitUser anotherHostUser,
            String customData) {
            if (startPKDialog != null && startPKDialog.isShowing()) {
                startPKDialog.dismiss();
            }
        }
    });
}

public void addPKButton(ZegoUIKitPrebuiltLiveStreamingFragment fragment) {
    PKButton pkButton = new PKButton(this);
    int size = Utils.dp2px(36f, getResources().getDisplayMetrics());
    int marginTop = Utils.dp2px(10f, getResources().getDisplayMetrics());
    int marginBottom = Utils.dp2px(16f, getResources().getDisplayMetrics());
    int marginEnd = Utils.dp2px(8, getResources().getDisplayMetrics());
    LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, size);
    layoutParams.topMargin = marginTop;
    layoutParams.bottomMargin = marginBottom;
    layoutParams.rightMargin = marginEnd;
    pkButton.setLayoutParams(layoutParams);
    fragment.addButtonToBottomMenuBar(Collections.singletonList(pkButton), ZegoLiveStreamingRole.HOST);
}



// MutePKUserButton.java
public class MutePKUserButton extends ZTextButton {

    public MutePKUserButton(@NonNull Context context) {
        super(context);
    }

    public MutePKUserButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MutePKUserButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void initView() {
        super.initView();
        setBackgroundResource(R.drawable.livestreaming_bg_cohost_btn);
        setGravity(Gravity.CENTER);
        setTextColor(Color.parseColor("#cccccc"));
        setMinWidth(Utils.dp2px(36, getResources().getDisplayMetrics()));
        int padding = Utils.dp2px(8, getResources().getDisplayMetrics());
        setPadding(padding, 0, padding, 0);
        updateButton();
        ZegoLiveStreamingManager.getInstance().addLiveStreamingListener(new ZegoLiveStreamingListener() {
            @Override
            public void onOtherHostMuted(String userID, boolean muted) {
                updateButton();
            }
        });
    }

    @Override
    protected void afterClick() {
        boolean pkUserMuted = ZegoLiveStreamingManager.getInstance().isAnotherHostMuted();
        ZegoLiveStreamingManager.getInstance().muteAnotherHostAudio(!pkUserMuted, null);
    }

    private void updateButton() {
        boolean pkUserMuted = ZegoLiveStreamingManager.getInstance().isAnotherHostMuted();
        if (pkUserMuted) {
            setText("Unmute user");
        } else {
            setText("Mute user");
        }
    }
}


// PKButton.java
public class PKButton extends ZTextButton {

    public PKButton(@NonNull Context context) {
        super(context);
    }

    public PKButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public PKButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void initView() {
        super.initView();
        setText("PK");
        setBackgroundResource(R.drawable.livestreaming_bg_cohost_btn);
        setGravity(Gravity.CENTER);
        setTextColor(Color.parseColor("#cccccc"));
        setMinWidth(Utils.dp2px(36, getResources().getDisplayMetrics()));
        int padding = Utils.dp2px(8, getResources().getDisplayMetrics());
        setPadding(padding, 0, padding, 0);

        ZegoLiveStreamingManager.getInstance().addLiveStreamingListener(new ZegoLiveStreamingListener() {
            @Override
            public void onPKStarted() {
                updateUI();
            }

            @Override
            public void onPKEnded() {
                updateUI();
            }

            @Override
            public void onOutgoingPKBattleRequestTimeout(String requestID, ZegoUIKitUser anotherHost) {
                updateUI();
                ZegoLiveStreamingManager.getInstance()
                    .showTopTips(getContext().getString(R.string.livestreaming_send_pk_no_reply), false);
            }

            @Override
            public void onOutgoingPKBattleRequestRejected(int reason, ZegoUIKitUser anotherHostUser) {
                updateUI();
                if (reason == ZegoLiveStreamingPKBattleRejectCode.HOST_REJECT.ordinal()) {
                    ZegoLiveStreamingManager.getInstance()
                        .showTopTips(getContext().getString(R.string.livestreaming_send_pk_rejected), false);
                } else {
                    ZegoLiveStreamingManager.getInstance()
                        .showTopTips(getContext().getString(R.string.livestreaming_send_pk_busy), false);
                }
            }

            @Override
            public void onOutgoingPKBattleRequestAccepted(String anotherHostLiveID, ZegoUIKitUser anotherHostUser) {
                ZegoLiveStreamingManager.getInstance()
                    .startPKBattleWith(anotherHostLiveID, anotherHostUser.userID, anotherHostUser.userName);
            }
        });
    }

    @Override
    protected void afterClick() {
        super.afterClick();
        PKRequest pkRequest = ZegoLiveStreamingManager.getInstance().getSendPKStartRequest();
        if (pkRequest == null) {
            if (ZegoLiveStreamingManager.getInstance().getPKInfo() == null) {
                Builder builder = new Builder(getContext());
                View layout = LayoutInflater.from(getContext())
                    .inflate(R.layout.livestreaming_dialog_pkinput, null, false);
                TextInputLayout inputLayout = layout.findViewById(R.id.dialog_pk_edittext);
                Button button = layout.findViewById(R.id.dialog_pk_button);
                builder.setView(layout);
                AlertDialog alertDialog = builder.create();
                alertDialog.show();
                button.setOnClickListener(view -> {
                    EditText editText = inputLayout.getEditText();
                    if (!TextUtils.isEmpty(editText.getText())) {
                        ZegoLiveStreamingManager.getInstance()
                            .sendPKBattleRequest(editText.getText().toString(), new UserRequestCallback() {
                                @Override
                                public void onUserRequestSend(int errorCode, String requestID) {
                                    if (errorCode != 0) {
                                        ZegoLiveStreamingManager.getInstance().showTopTips(
                                            getContext().getString(R.string.livestreaming_send_pk_error, errorCode),
                                            false);
                                    }
                                    updateUI();
                                }
                            });
                        alertDialog.dismiss();
                    }
                });
            } else {
                ZegoLiveStreamingManager.getInstance().stopPKBattle();
            }
        } else {
            ZegoLiveStreamingManager.getInstance().cancelPKBattleRequest(new UserRequestCallback() {
                @Override
                public void onUserRequestSend(int errorCode, String requestID) {
                    updateUI();
                }
            });
        }
    }

    public void updateUI() {
        PKInfo pkInfo = ZegoLiveStreamingManager.getInstance().getPKInfo();
        if (pkInfo != null) {
            setText("End PK");
        } else {
            PKRequest sendPKStartRequest = ZegoLiveStreamingManager.getInstance().getSendPKStartRequest();
            if (sendPKStartRequest == null) {
                setText("PK");
            } else {
                setText("Cancel PK");
            }
        }
    }
}

Previous

使用 Token 鉴权

Next

发送虚拟礼物