Many popular live streaming platforms include a “PK” feature (short for “Player Kill” or “versus battle”), where hosts compete to receive gifts from viewers, and the host who gets the most gifts wins. In some cases, a last-second gift from a fan can overturn what seemed like a sure result, providing a thrilling experience for the audience. For the streaming platform, the PK feature typically grants hosts advanced permissions and is a key driver of engagement.
This article will guide you through integrating a PK feature into an Android live streaming app.
We’ll build upon an existing live streaming setup using Tencent RTC’s **TUILiveKit component.**
Custom Functionality
Custom Battle waiting countdown style
If you need the custom battle waiting countdown style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/anchor/component/livestreaming/battle/
├── BattleCountdownBackView.java // Battle waiting countdown background style
└── BattleCountdownView.java // Battle waiting countdown foreground style
Custom Definition Dual Battle Score Style
If you need the custom Definition Dual battle score style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/SingleBattleScoreView.java
public class SingleBattleScoreView extends FrameLayout {
...
}
Custom Definition Multi Battle Score Style
If you need the custom Definition Multi Battle score style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/BattleMemberInfoView.java
public class BattleMemberInfoView extends FrameLayout {
...
}
Custom Definition Battle Score Result Style
If you need a Custom Definition Battle Score Result Style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/BattleInfoView.java
public class BattleInfoView extends BasicView {
...
private void showBattleResult(int type) {
// Battle Result Display
}
}
Key code
Anchor Battle
TUILiveKit Anchor battle feature is mainly based on BattleService
. You can obtain the battle management object through store.serviceCenter.battleService
and call the relevant battle API functions to implement the battle feature. For example, in the interaction between Anchor A and B, refer to the diagram below for the specific interaction sequence.
Anchor A initiates Battle
Anchor A initiates a battle by calling requestBattle
, passing the maximum Battle duration in parameter config
, whether the inviter needs to reply with accept/reject, and passing anchor B's userId in parameter userIdList
, and passing the battle invitation wait duration in parameter timeout
.
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/controller/BattleController.java
public void requestBattle(List<String> roomIdList, int timeout) {
TUILiveBattleManager.BattleConfig config = new TUILiveBattleManager.BattleConfig();
config.duration = BattleState.BATTLE_DURATION;
config.needResponse = mBattleState.mNeedResponse;
config.extensionInfo = "";
mLiveService.requestBattle(config, roomIdList, timeout, new TUILiveBattleManager.BattleRequestCallback() {
@Override
public void onSuccess(TUILiveBattleManager.BattleInfo battleInfo,
Map<String, TUILiveBattleManager.BattleCode> map) {
mBattleState.mBattleId = battleInfo.battleId;
mBattleState.mBattleConfig.copy(config);
List<BattleState.BattleUser> sendRequests = mBattleState.mSentBattleRequests.get();
for (Map.Entry<String, TUILiveBattleManager.BattleCode> entry : map.entrySet()) {
String key = entry.getKey();
TUILiveBattleManager.BattleCode code = entry.getValue();
if (code == TUILiveBattleManager.BattleCode.SUCCESS) {
for (ConnectionState.ConnectionUser user : mConnectionState.connectedUsers.get()) {
if (TextUtils.equals(user.userId, key)) {
sendRequests.add(new BattleState.BattleUser(user));
break;
}
}
} else {
notifyToast(convertCodeToString(entry.getValue()));
}
}
mBattleState.mSentBattleRequests.set(sendRequests);
}
@Override
public void onError(TUICommonDefine.Error error, String s) {
ErrorHandler.onError(error);
mBattleState.mSentBattleRequests.clear();
}
});
}
Anchor A can receive the request acceptance callback via onBattleRequestAccept
.
Anchor receives a battle request
Anchor B receives the battle request callback via onBattleRequestReceived
.
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/observer/LiveBattleManagerObserver.java
@Override
public void onBattleRequestReceived(BattleInfo battleInfo, BattleUser inviter, BattleUser invitee) {
LiveKitLog.info(mTag + " onBattleRequestReceived:[battleInfo:" + new Gson().toJson(battleInfo)
+ ", inviter:" + new Gson().toJson(inviter) + ", invitee:" + new Gson().toJson(invitee) + "]");
mBattleController.onBattleRequestReceived(battleInfo, inviter);
}
Anchor B accepts the battle request by calling acceptBattle
.
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/controller/BattleController.java
public void accept() {
mLiveService.acceptBattle(mBattleState.mBattleId, new TUIRoomDefine.ActionCallback() {
@Override
public void onSuccess() {
}
@Override
public void onError(TUICommonDefine.Error error, String s) {
}
});
}
Anchors A, B, and the audience in the room can receive the battle start callback through onBattleStarted
.
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/observer/LiveBattleManagerObserver.java
@Override
public void onBattleStarted(BattleInfo battleInfo) {
LiveKitLog.info(mTag + " onBattleStarted:[battleInfo:" + new Gson().toJson(battleInfo) + "]");
mBattleController.onBattleStarted(battleInfo);
}
The anchor exits the battle
For example, when anchor B exits the battle, the interaction sequence can be referenced from the diagram below.
Anchor B calls exitBattle
to exit the battle.
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/controller/BattleController.java
public void exitBattle() {
mLiveService.exitBattle(mBattleState.mBattleId, new TUIRoomDefine.ActionCallback() {
@Override
public void onSuccess() {
mBattleState.mSentBattleRequests.clear();
mBattleState.mBattledUsers.clear();
removeBattleRequestReceived();
}
@Override
public void onError(TUICommonDefine.Error error, String s) {
}
});
}
Anchors A, B, and the room audience receive the onBattleEnded
callback and the battle end notification.
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/observer/LiveBattleManagerObserver.java
@Override
public void onBattleEnded(BattleInfo battleInfo, BattleStoppedReason reason) {
LiveKitLog.info(mTag + " onBattleEnded:[battleInfo:"
+ new Gson().toJson(battleInfo) + ", reason:" + reason + "]");
mBattleController.onBattleEnded(battleInfo);
}
Now you can add a host PK feature to your live streaming app! For more details on additional features, please refer to the documentation.
My name is Susie. I am a writer and Media Service Product Manager. I work with startups across the globe to build real-time communication solutions using SDK and APIs.
If you want to build face filter or other special effect into your app, welcome to contact us.
Top comments (0)