ライブ配信アプリにホストPK機能を追加する方法 | Androidチュートリアル
多くの人気ライブ配信プラットフォームでは、「PK」(「Player Kill」または「対戦バトル」の略)機能を導入しており、配信者同士が視聴者からのギフト数を競い、最も多くのギフトを獲得した側が勝利となります。場合によっては、ファンからの最後の数秒の大型ギフトによって、ほぼ決まっていた勝敗が覆ることもあり、視聴者にとっては非常にスリリングな体験となります。プラットフォームにとっては、PK機能は配信者に高度な権限を付与し、エンゲージメントを高める重要な仕組みです。
本記事では、PK機能をAndroidライブ配信アプリに統合する方法を解説します。
Tencent RTCのTUILiveKitコンポーネントを使用した既存のライブ配信環境をベースに進めます。
カスタム機能
カスタムバトル待機カウントダウンスタイル
バトル待機カウントダウンを独自にカスタマイズしたい場合は、以下のパスのコードを参照して変更してください。
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/anchor/component/livestreaming/battle/
├── BattleCountdownBackView.java // バトル待機カウントダウン背景スタイル
└── BattleCountdownView.java // バトル待機カウントダウン前景スタイル
カスタム定義デュアルバトルスコアスタイル
デュアルバトルスコアを独自にカスタマイズしたい場合は、以下のパスのコードを参照して変更してください。
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/SingleBattleScoreView.java
public class SingleBattleScoreView extends FrameLayout {
...
}
カスタム定義マルチバトルスコアスタイル
マルチバトルスコアを独自にカスタマイズしたい場合は、以下のパスのコードを参照して変更してください。
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/BattleMemberInfoView.java
public class BattleMemberInfoView extends FrameLayout {
...
}
カスタム定義バトルスコア結果スタイル
バトルスコア結果表示を独自にカスタマイズしたい場合は、以下のパスのコードを参照してください。
// 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) {
// バトル結果表示
}
}
主要コード
配信者バトル
TUILiveKit の配信者バトル機能は主に BattleService
に基づいており、store.serviceCenter.battleService
を通じてバトル管理オブジェクトを取得し、関連するバトルAPIを呼び出すことでバトル機能を実装します。たとえば、配信者Aと配信者B間のやり取りにおいては、下記のシーケンス図を参考にしてください。
配信者Aがバトルを開始
配信者Aは requestBattle
を呼び出してバトルを開始します。config
にバトルの最大継続時間を渡し、招待者が承諾/拒否の返答が必要かどうかを指定し、招待する相手である配信者Bの userId をuserIdList
に設定、そしてバトル招待待機時間を 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();
}
});
}
配信者Aは、onBattleRequestAccept
を介してリクエスト受諾のコールバックを受け取ります。
配信者がバトルリクエストを受信
配信者Bは、onBattleRequestReceived
を通じてバトルリクエストのコールバックを受け取り、acceptBattle
を呼び出すことでリクエストを受諾します。
// 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);
}
// 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) {
}
});
}
配信者A、B、およびルーム内の視聴者は 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);
}
配信者がバトルから退出
例として、配信者Bがバトルを退出する場合のシーケンス図は下記を参照してください。
配信者Bは exitBattle
を呼び出すことでバトルを退出します。
// 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) {
}
});
}
配信者A、B、およびルーム内の視聴者は onBattleEnded
を通じてバトル終了のコールバックと通知を受け取ります。
// 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);
}
これで、ライブ配信アプリに配信者のPK機能を追加できます!詳しい機能については、ドキュメント をご参照ください。
私はSusieと申します。ライター兼メディアサービスのプロダクトマネージャーとして、世界中のスタートアップと協力し、SDKやAPIを活用したリアルタイムコミュニケーションソリューションの構築を支援しています。
アプリにフェイスフィルターやその他の特殊効果機能を実装したい場合は、ぜひお問い合わせください。
Discussion