PK 连麦
功能简介
PK 连麦,指两个直播间进行主播连麦 PK 互动,应用于秀场、游戏、电商等直播场景,可以提升直播间内容的丰富性、吸引更多的粉丝流,提升直播间的娱乐气氛。
前提条件
在开始之前,请确保您完成了以下步骤:
- 请参考 快速开始(适用于连麦) 完成集成相关操作。
- 请联系 ZEGO 技术支持激活混流服务。
实现流程
主播在自己的直播间开始后,可以向他们想要连接的主播发送 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;
}
其中,ZegoLiveStreamingPKBattleViewProvider
和 ZegoLiveStreamingPKBattleViewBuilder
的定义如下:
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;
}
};
效果将如下所示: