语音房添加

This commit is contained in:
18401019693 2024-01-10 15:48:10 +08:00
parent 85ccbcccae
commit 926a1a3cb6
46 changed files with 1769 additions and 133 deletions

View File

@ -23,6 +23,7 @@ import com.alibaba.fastjson.JSONObject;
import com.blankj.utilcode.util.Utils; import com.blankj.utilcode.util.Utils;
import com.facebook.appevents.AppEventsLogger; import com.facebook.appevents.AppEventsLogger;
import com.fm.openinstall.OpenInstall; import com.fm.openinstall.OpenInstall;
import com.google.gson.Gson;
import com.shayu.phonelive.utils.LogUtils; import com.shayu.phonelive.utils.LogUtils;
import com.tencent.imsdk.v2.V2TIMGroupMemberInfo; import com.tencent.imsdk.v2.V2TIMGroupMemberInfo;
import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMManager;
@ -36,12 +37,14 @@ import com.yunbao.common.CommonAppContext;
import com.yunbao.common.Constants; import com.yunbao.common.Constants;
import com.yunbao.common.bean.AnchorStartLiveBean; import com.yunbao.common.bean.AnchorStartLiveBean;
import com.yunbao.common.bean.CrashSaveBean; import com.yunbao.common.bean.CrashSaveBean;
import com.yunbao.common.event.SudGameSocketImEvent;
import com.yunbao.common.manager.imrongcloud.InstructorSendReward; import com.yunbao.common.manager.imrongcloud.InstructorSendReward;
import com.yunbao.common.manager.imrongcloud.InstructorSendRewardProvider; import com.yunbao.common.manager.imrongcloud.InstructorSendRewardProvider;
import com.yunbao.common.manager.imrongcloud.MessageIMManager; import com.yunbao.common.manager.imrongcloud.MessageIMManager;
import com.yunbao.common.manager.imrongcloud.RecommendLiveRoom; import com.yunbao.common.manager.imrongcloud.RecommendLiveRoom;
import com.yunbao.common.manager.imrongcloud.RongcloudIMManager; import com.yunbao.common.manager.imrongcloud.RongcloudIMManager;
import com.yunbao.common.utils.AppManager; import com.yunbao.common.utils.AppManager;
import com.yunbao.common.utils.Bus;
import com.yunbao.common.utils.GoogleUtils; import com.yunbao.common.utils.GoogleUtils;
import com.yunbao.common.utils.L; import com.yunbao.common.utils.L;
import com.yunbao.common.utils.SpUtil; import com.yunbao.common.utils.SpUtil;
@ -210,6 +213,11 @@ public class AppContext extends CommonAppContext {
SocketReceiveBean received = JSON.parseObject(content.getContent(), SocketReceiveBean.class); SocketReceiveBean received = JSON.parseObject(content.getContent(), SocketReceiveBean.class);
JSONObject map = received.getMsg().getJSONObject(0); JSONObject map = received.getMsg().getJSONObject(0);
sendStartAnchorLive(map); sendStartAnchorLive(map);
} else if (message.getTargetId().contains("v")) {
String contentJson = ((TextMessage) message.getContent()).getContent();
Log.e("wewe", contentJson);
SudGameSocketImEvent sudGameSocketImEvent = new Gson().fromJson(contentJson, SudGameSocketImEvent.class);
Bus.get().post(sudGameSocketImEvent);
} }
//主播页面 //主播页面
if (TextUtils.isEmpty(PortraitLiveManager.liveID) && SocketRyClient.mSocketHandler != null) { if (TextUtils.isEmpty(PortraitLiveManager.liveID) && SocketRyClient.mSocketHandler != null) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

View File

@ -3,29 +3,40 @@ package com.yunbao.common.activity;
import android.app.Activity; import android.app.Activity;
import android.view.View; import android.view.View;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.lxj.xpopup.XPopup; import com.lxj.xpopup.XPopup;
import com.makeramen.roundedimageview.RoundedImageView;
import com.yunbao.common.R; import com.yunbao.common.R;
import com.yunbao.common.adapter.SudGameChatAdapter;
import com.yunbao.common.adapter.SudGameUserListAdapter;
import com.yunbao.common.bean.CheckRemainingBalance; import com.yunbao.common.bean.CheckRemainingBalance;
import com.yunbao.common.bean.CreateSudRoomModel; import com.yunbao.common.bean.CreateSudRoomModel;
import com.yunbao.common.bean.CustomSidebarChildModel; import com.yunbao.common.bean.CustomSidebarChildModel;
import com.yunbao.common.bean.CustomSidebarInfoModel; import com.yunbao.common.bean.CustomSidebarInfoModel;
import com.yunbao.common.bean.SudGameChatImModel;
import com.yunbao.common.dialog.SudGameInputPopupWindow;
import com.yunbao.common.event.CheckRemainingBalanceEvent; import com.yunbao.common.event.CheckRemainingBalanceEvent;
import com.yunbao.common.event.SudGameSocketImEvent;
import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.glide.ImgLoader;
import com.yunbao.common.http.base.HttpCallback; import com.yunbao.common.http.base.HttpCallback;
import com.yunbao.common.http.live.LiveNetManager; import com.yunbao.common.http.live.LiveNetManager;
import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMLoginManager;
import com.yunbao.common.manager.imrongcloud.GameMicManager;
import com.yunbao.common.sud.QuickStartGameViewModel; import com.yunbao.common.sud.QuickStartGameViewModel;
import com.yunbao.common.sud.model.GameConfigModel; import com.yunbao.common.sud.model.GameConfigModel;
import com.yunbao.common.sud.model.GameViewInfoModel;
import com.yunbao.common.sud.state.SudMGPMGState; import com.yunbao.common.sud.state.SudMGPMGState;
import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.Bus;
import com.yunbao.common.utils.DpUtil;
import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.ToastUtil;
import com.yunbao.common.views.LiveSudGameHistoryPopup; import com.yunbao.common.views.LiveSudGameHistoryPopup;
import com.yunbao.common.views.TopGradual;
import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.common.views.weight.ViewClicksAntiShake;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
@ -35,15 +46,28 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
public class SudGameActivity extends AbsActivity { import cn.rongcloud.rtc.api.RCRTCEngine;
import cn.rongcloud.rtc.api.RCRTCRemoteUser;
import cn.rongcloud.rtc.api.RCRTCRoom;
import cn.rongcloud.rtc.api.stream.RCRTCInputStream;
import cn.rongcloud.rtc.base.RTCErrorCode;
public class SudGameActivity extends AbsActivity implements GameMicManager.MeetingCallback {
private FrameLayout gameContainer; private FrameLayout gameContainer;
private long mInteractionID; private long mInteractionID;
private String mLiveUid; private String mLiveUid;
private final QuickStartGameViewModel gameViewModel = new QuickStartGameViewModel(); // 创建ViewModel private final QuickStartGameViewModel gameViewModel = new QuickStartGameViewModel(); // 创建ViewModel
private CreateSudRoomModel mCreateSudRoomModel; private CreateSudRoomModel mCreateSudRoomModel;
private TextView gameTitle, roomName, roomNumber; private TextView roomName, roomNumber;
private RoundedImageView mAvatar; private GameMicManager gameMicManager;
private ImageView gameCloseWheat, gameSeat;
private boolean disable = true, publishDefault = false;
private RecyclerView chatList, userList;
private SudGameChatAdapter mLiveChatAdapter;
private SudGameUserListAdapter sudGameUserListAdapter;
@Override @Override
protected int getLayoutId() { protected int getLayoutId() {
return R.layout.activity_sud_game; return R.layout.activity_sud_game;
@ -56,7 +80,9 @@ public class SudGameActivity extends AbsActivity {
initView(); initView();
initDate(); initDate();
} }
private List<CustomSidebarChildModel> customSidebarChildModels = new ArrayList<>(); private List<CustomSidebarChildModel> customSidebarChildModels = new ArrayList<>();
private void initDate() { private void initDate() {
LiveNetManager.get(mContext) LiveNetManager.get(mContext)
.getCustomSidebarInfo("1", new HttpCallback<List<CustomSidebarInfoModel>>() { .getCustomSidebarInfo("1", new HttpCallback<List<CustomSidebarInfoModel>>() {
@ -75,10 +101,21 @@ public class SudGameActivity extends AbsActivity {
} }
}); });
gameMicManager = new GameMicManager();
gameMicManager.attachView(this);
gameMicManager.config(this);
gameMicManager.joinRoom(mLiveUid);
// 设置禁用麦克风采集
RCRTCEngine.getInstance().getDefaultAudioStream().setMicrophoneDisable(disable);
ImgLoader.display(mContext, R.mipmap.icon_game_close_wheat, gameCloseWheat);
gameCloseWheat.setVisibility(View.INVISIBLE);
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
Bus.getOff(this); Bus.getOff(this);
gameMicManager.leaveRoom();
gameMicManager.detachView();
super.onDestroy(); super.onDestroy();
} }
@ -89,15 +126,33 @@ public class SudGameActivity extends AbsActivity {
mLiveUid = mCreateSudRoomModel.getSudGameRoomId(); mLiveUid = mCreateSudRoomModel.getSudGameRoomId();
gameContainer = findViewById(R.id.game_container); gameContainer = findViewById(R.id.game_container);
gameTitle = findViewById(R.id.game_title);
roomName = findViewById(R.id.room_name); roomName = findViewById(R.id.room_name);
roomNumber = findViewById(R.id.room_number); roomNumber = findViewById(R.id.room_number);
mAvatar = findViewById(R.id.avatar); gameCloseWheat = findViewById(R.id.game_close_wheat);
gameSeat = findViewById(R.id.game_seat);
chatList = findViewById(R.id.chat_list);
userList = findViewById(R.id.user_list);
//聊天栏
FrameLayout.LayoutParams params1 = (FrameLayout.LayoutParams)
chatList.getLayoutParams();
params1.topMargin = DpUtil.dp2px(65);
chatList.setLayoutParams(params1);
chatList.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(mContext);
layoutManager.setOrientation(RecyclerView.VERTICAL);
layoutManager.setStackFromEnd(true);
chatList.setLayoutManager(layoutManager);
chatList.addItemDecoration(new TopGradual());
chatList.setItemViewCacheSize(10);
mLiveChatAdapter = new SudGameChatAdapter(mContext);
chatList.setAdapter(mLiveChatAdapter);
sudGameUserListAdapter = new SudGameUserListAdapter(new ArrayList<>());
userList.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
userList.setAdapter(sudGameUserListAdapter);
if (mCreateSudRoomModel != null) { if (mCreateSudRoomModel != null) {
gameTitle.setText(mCreateSudRoomModel.getSudGameName());
roomName.setText(mCreateSudRoomModel.getRoomName()); roomName.setText(mCreateSudRoomModel.getRoomName());
roomNumber.setText(mCreateSudRoomModel.getSudGameRoomId()); roomNumber.setText(mCreateSudRoomModel.getSudGameRoomId());
ImgLoader.display(mContext, mCreateSudRoomModel.getAvatar(), mAvatar);
} }
ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.exit), new ViewClicksAntiShake.ViewClicksCallBack() { ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.exit), new ViewClicksAntiShake.ViewClicksCallBack() {
@Override @Override
@ -115,6 +170,52 @@ public class SudGameActivity extends AbsActivity {
.asCustom(new LiveSudGameHistoryPopup(mContext, customSidebarChildModels)).show(); .asCustom(new LiveSudGameHistoryPopup(mContext, customSidebarChildModels)).show();
} }
}); });
ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.game_seat), new ViewClicksAntiShake.ViewClicksCallBack() {
@Override
public void onViewClicks() {
if (publishDefault) {
disable = true;
// 设置禁用麦克风采集
RCRTCEngine.getInstance().getDefaultAudioStream().setMicrophoneDisable(disable);
ImgLoader.display(mContext, R.mipmap.icon_game_close_wheat, gameCloseWheat);
gameMicManager.unPublishStreams();
} else {
gameMicManager.publishDefaultAVStream();
}
}
});
ViewClicksAntiShake.clicksAntiShake(gameCloseWheat, new ViewClicksAntiShake.ViewClicksCallBack() {
@Override
public void onViewClicks() {
if (disable) {
disable = false;
// 设置禁用麦克风采集
RCRTCEngine.getInstance().getDefaultAudioStream().setMicrophoneDisable(disable);
ImgLoader.display(mContext, R.mipmap.icon_game_open_wheat, gameCloseWheat);
} else {
disable = true;
// 设置禁用麦克风采集
RCRTCEngine.getInstance().getDefaultAudioStream().setMicrophoneDisable(disable);
ImgLoader.display(mContext, R.mipmap.icon_game_close_wheat, gameCloseWheat);
}
}
});
ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.game_review_input), new ViewClicksAntiShake.ViewClicksCallBack() {
@Override
public void onViewClicks() {
new XPopup.Builder(mContext)
.enableDrag(false)
.asCustom(new SudGameInputPopupWindow(mContext, new SudGameInputPopupWindow.SudGameInputCallBack() {
@Override
public void sendMessage(String textMessage) {
gameMicManager.sendMessage(textMessage);
}
}))
.show();
}
});
gameViewModel.gameViewLiveData.observe(this, new Observer<View>() { gameViewModel.gameViewLiveData.observe(this, new Observer<View>() {
@Override @Override
public void onChanged(View view) { public void onChanged(View view) {
@ -122,7 +223,9 @@ public class SudGameActivity extends AbsActivity {
gameContainer.removeAllViews(); gameContainer.removeAllViews();
} else { // 把游戏View添加到容器内 } else { // 把游戏View添加到容器内
gameContainer.addView(view, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); gameContainer.addView(view, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
} }
} }
}); });
// 加载游戏参数定义可查看BaseGameViewModel.switchGame()方法注释 // 加载游戏参数定义可查看BaseGameViewModel.switchGame()方法注释
@ -137,6 +240,7 @@ public class SudGameActivity extends AbsActivity {
gameConfigModel.ui.game_settle_again_btn.custom = true; gameConfigModel.ui.game_settle_again_btn.custom = true;
gameConfigModel.ui.start_btn.custom = true; gameConfigModel.ui.start_btn.custom = true;
// SudMGP平台64bit游戏ID // SudMGP平台64bit游戏ID
gameViewModel.switchGame((Activity) mContext, mLiveUid, mInteractionID); gameViewModel.switchGame((Activity) mContext, mLiveUid, mInteractionID);
// gameViewModel.sudFSTAPPDecorator.notifyAPPCommonSelfIn(true, -1, true, 1); // gameViewModel.sudFSTAPPDecorator.notifyAPPCommonSelfIn(true, -1, true, 1);
@ -147,6 +251,13 @@ public class SudGameActivity extends AbsActivity {
// //
// } // }
// }); // });
// 设置游戏安全操作区域
GameViewInfoModel.GameViewRectModel gameViewRectModel = new GameViewInfoModel.GameViewRectModel();
gameViewRectModel.left = 0;
gameViewRectModel.top = DpUtil.dp2px(155);
gameViewRectModel.right = 0;
gameViewRectModel.bottom = DpUtil.dp2px(155);
gameViewModel.gameViewRectModel = gameViewRectModel;
} }
@ -156,6 +267,7 @@ public class SudGameActivity extends AbsActivity {
switch (event.getSudMGPMGState()) { switch (event.getSudMGPMGState()) {
case SudMGPMGState.MG_COMMON_SELF_CLICK_JOIN_BTN: case SudMGPMGState.MG_COMMON_SELF_CLICK_JOIN_BTN:
case SudMGPMGState.MG_COMMON_SELF_CLICK_GAME_SETTLE_AGAIN_BTN: case SudMGPMGState.MG_COMMON_SELF_CLICK_GAME_SETTLE_AGAIN_BTN:
LiveNetManager.get(mContext).checkRemainingBalance(mCreateSudRoomModel.getSudGameRoomId(), new HttpCallback<CheckRemainingBalance>() { LiveNetManager.get(mContext).checkRemainingBalance(mCreateSudRoomModel.getSudGameRoomId(), new HttpCallback<CheckRemainingBalance>() {
@Override @Override
public void onSuccess(CheckRemainingBalance data) { public void onSuccess(CheckRemainingBalance data) {
@ -211,4 +323,85 @@ public class SudGameActivity extends AbsActivity {
} }
@Override
public void onJoinRoomSuccess(RCRTCRoom rcrtcRoom) {
// 主动订阅远端用户发布的资源
gameMicManager.subscribeAVStream();
}
@Override
public void onJoinRoomFailed(RTCErrorCode rtcErrorCode) {
ToastUtil.show("加入失败 ");
}
@Override
public void onPublishSuccess() {
runOnUiThread(new Runnable() {
@Override
public void run() {
ImgLoader.display(mContext, R.mipmap.icon_game_hang_up, gameSeat);
publishDefault = true;
gameCloseWheat.setVisibility(View.VISIBLE);
disable = false;
// 设置禁用麦克风采集
RCRTCEngine.getInstance().getDefaultAudioStream().setMicrophoneDisable(disable);
ImgLoader.display(mContext, R.mipmap.icon_game_open_wheat, gameCloseWheat);
}
});
}
@Override
public void onPublishFailed() {
ToastUtil.show("发布失败 ");
}
@Override
public void onSubscribeSuccess(List<RCRTCInputStream> inputStreamList) {
ToastUtil.show("订阅成功 ");
}
@Override
public void onSubscribeFailed() {
ToastUtil.show("订阅失败 ");
}
@Override
public void onUserJoined(RCRTCRemoteUser rcrtcRemoteUser) {
}
@Override
public void onUserLeft(RCRTCRemoteUser rcrtcRemoteUser) {
}
@Override
public void insertItem(SudGameChatImModel sudGameChatImModel) {
mLiveChatAdapter.insertItem(sudGameChatImModel);
}
@Override
public void onUnPublishStreamsSuccess() {
runOnUiThread(new Runnable() {
@Override
public void run() {
ImgLoader.display(mContext, R.mipmap.icon_game_seat, gameSeat);
publishDefault = false;
gameCloseWheat.setVisibility(View.INVISIBLE);
}
});
}
@Override
public void onUnPublishStreamsFailed() {
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onSudGameSocketImEvent(SudGameSocketImEvent event) {
gameMicManager.processingMessage(event);
}
} }

View File

@ -0,0 +1,122 @@
package com.yunbao.common.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.yunbao.common.R;
import com.yunbao.common.bean.SudGameChatImModel;
import com.yunbao.common.views.SudGameChatViewHolder;
import java.util.ArrayList;
import java.util.List;
public class SudGameChatAdapter extends RecyclerView.Adapter {
private boolean isBottom = false;
List<SudGameChatImModel> sudGameChatImModels = new ArrayList<>();
private RecyclerView mRecyclerView;
private LinearLayoutManager mLayoutManager;
private int mRecyclerViewScrolledDy;
private Context mContext;
public SudGameChatAdapter(Context mContext) {
this.mContext = mContext;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View herdView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_sud_game_chat_item_holder, parent, false);
return new SudGameChatViewHolder(herdView);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof SudGameChatViewHolder) {
SudGameChatViewHolder itemViewHolder = (SudGameChatViewHolder) holder;
itemViewHolder.sudGameChat(sudGameChatImModels.get(position));
}
}
@Override
public int getItemCount() {
return sudGameChatImModels.size();
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (isBottom && dy >= 0) return;
mRecyclerViewScrolledDy = dy;
isBottom = false;
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == 0 && isSlideToBottom(recyclerView)) {
mRecyclerViewScrolledDy = 0;
scrollToBottom();
isBottom = true;
} else if (newState == 0) {
isBottom = false;
}
}
});
}
public synchronized void insertItem(SudGameChatImModel bean) {
if (bean == null) {
return;
}
int size = sudGameChatImModels.size();
//设置最大展示99条消息
if (size >= 100 && (isBottom || mRecyclerViewScrolledDy == 0)) {
sudGameChatImModels.subList(0, 50).clear();
notifyItemRangeRemoved(0, 50);
}
sudGameChatImModels.add(bean);
if (getItemCount() == 1) {
notifyDataSetChanged();
} else {
notifyItemInserted(getItemCount());
}
if (isBottom || mRecyclerViewScrolledDy == 0) {
scrollToBottom();
}
}
/**
* 判断是否滚到底部
*
* @param recyclerView
* @return
*/
public boolean isSlideToBottom(RecyclerView recyclerView) {
if (recyclerView == null) return false;
if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())
return true;
return false;
}
public void scrollToBottom() {
if (sudGameChatImModels.size() > 0) {
mRecyclerView.smoothScrollToPosition(getItemCount());
}
mRecyclerViewScrolledDy = 0;
}
}

View File

@ -0,0 +1,61 @@
package com.yunbao.common.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.yunbao.common.R;
import com.yunbao.common.bean.SudGameUserModel;
import com.yunbao.common.views.SudGameChatViewHolder;
import com.yunbao.common.views.SudGameUserListViewHolder;
import java.util.ArrayList;
import java.util.List;
public class SudGameUserListAdapter extends RecyclerView.Adapter {
private List<SudGameUserModel> gameUserModels = new ArrayList<>();
public SudGameUserListAdapter(List<SudGameUserModel> gameUserModels) {
if (gameUserModels.size() < 7) {
this.gameUserModels.addAll(gameUserModels);
for (int i = 0; i < this.gameUserModels.size(); i++) {
this.gameUserModels.get(i).setNullUser(false);
}
int size = 7 - gameUserModels.size();
for (int i = 0; i < size; i++) {
this.gameUserModels.add(new SudGameUserModel().setNullUser(true));
}
} else if (gameUserModels.size() == 7) {
this.gameUserModels.addAll(gameUserModels);
for (int i = 0; i < this.gameUserModels.size(); i++) {
this.gameUserModels.get(i).setNullUser(false);
}
} else {
for (int i = 0; i < 7; i++) {
this.gameUserModels.add(gameUserModels.get(i).setNullUser(false));
}
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View herdView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_sud_game_user_list_holder, parent, false);
return new SudGameUserListViewHolder(herdView);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return gameUserModels.size();
}
}

View File

@ -0,0 +1,26 @@
package com.yunbao.common.bean;
public class SudGameChatImModel extends BaseModel {
//昵称
private String nickname;
//文字消息
private String textMessage;
public String getNickname() {
return nickname;
}
public SudGameChatImModel setNickname(String nickname) {
this.nickname = nickname;
return this;
}
public String getTextMessage() {
return textMessage;
}
public SudGameChatImModel setTextMessage(String textMessage) {
this.textMessage = textMessage;
return this;
}
}

View File

@ -0,0 +1,14 @@
package com.yunbao.common.bean;
public class SudGameUserModel extends BaseModel {
private boolean nullUser;
public boolean isNullUser() {
return nullUser;
}
public SudGameUserModel setNullUser(boolean nullUser) {
this.nullUser = nullUser;
return this;
}
}

View File

@ -0,0 +1,73 @@
package com.yunbao.common.dialog;
import android.content.Context;
import android.text.TextUtils;
import android.widget.EditText;
import androidx.annotation.NonNull;
import com.lxj.xpopup.core.BottomPopupView;
import com.yunbao.common.R;
import com.yunbao.common.utils.ToastUtil;
import com.yunbao.common.utils.WordUtil;
import com.yunbao.common.views.weight.ViewClicksAntiShake;
/***
* 游戏房字体输入
*/
public class SudGameInputPopupWindow extends BottomPopupView {
private EditText textMessage;
private SudGameInputCallBack sudGameInputCallBack;
public SudGameInputPopupWindow(@NonNull Context context, SudGameInputCallBack sudGameInputCallBack) {
super(context);
this.sudGameInputCallBack = sudGameInputCallBack;
}
// 返回自定义弹窗的布局
@Override
protected int getImplLayoutId() {
return R.layout.dialog_sud_game_input;
}
// 执行初始化操作比如findView设置点击或者任何你弹窗内的业务逻辑
@Override
protected void onCreate() {
super.onCreate();
initView();
initDate();
}
private void initView() {
textMessage = findViewById(R.id.text_message);
ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.send), new ViewClicksAntiShake.ViewClicksCallBack() {
@Override
public void onViewClicks() {
dialog.dismiss();
if (sudGameInputCallBack != null) {
String textMessageStr = textMessage.getText().toString();
if (!TextUtils.isEmpty(textMessageStr)) {
if (textMessageStr.length() > 100) {
ToastUtil.show(WordUtil.isNewZh() ? "超出字數限制" : "Exceed word limit");
} else {
sudGameInputCallBack.sendMessage(textMessageStr);
}
} else {
ToastUtil.show(WordUtil.getNewString(R.string.cannot_be_empty));
}
}
}
});
}
private void initDate() {
}
public interface SudGameInputCallBack {
void sendMessage(String textMessage);
}
}

View File

@ -0,0 +1,120 @@
package com.yunbao.common.event;
import com.google.gson.annotations.SerializedName;
import com.yunbao.common.bean.BaseModel;
import java.util.List;
public class SudGameSocketImEvent extends BaseModel {
@SerializedName("msg")
private List<MsgDTO> msg;
@SerializedName("retcode")
private String retcode;
@SerializedName("retmsg")
private String retmsg;
public List<MsgDTO> getMsg() {
return msg;
}
public void setMsg(List<MsgDTO> msg) {
this.msg = msg;
}
public String getRetcode() {
return retcode;
}
public void setRetcode(String retcode) {
this.retcode = retcode;
}
public String getRetmsg() {
return retmsg;
}
public void setRetmsg(String retmsg) {
this.retmsg = retmsg;
}
public static class MsgDTO {
@SerializedName("action")
private String action;
@SerializedName("uid")
private String uid;
@SerializedName("roomnum")
private String roomnum;
@SerializedName("ct")
private String ct;
@SerializedName("uname")
private String uname;
@SerializedName("_method_")
private String method;
@SerializedName("equipment")
private String equipment;
public String getAction() {
return action;
}
public MsgDTO setAction(String action) {
this.action = action;
return this;
}
public String getUid() {
return uid;
}
public MsgDTO setUid(String uid) {
this.uid = uid;
return this;
}
public String getRoomnum() {
return roomnum;
}
public MsgDTO setRoomnum(String roomnum) {
this.roomnum = roomnum;
return this;
}
public String getCt() {
return ct;
}
public MsgDTO setCt(String ct) {
this.ct = ct;
return this;
}
public String getUname() {
return uname;
}
public MsgDTO setUname(String uname) {
this.uname = uname;
return this;
}
public String getMethod() {
return method;
}
public MsgDTO setMethod(String method) {
this.method = method;
return this;
}
public String getEquipment() {
return equipment;
}
public MsgDTO setEquipment(String equipment) {
this.equipment = equipment;
return this;
}
}
}

View File

@ -0,0 +1,429 @@
package com.yunbao.common.manager.imrongcloud;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import com.google.gson.Gson;
import com.yunbao.common.CommonAppContext;
import com.yunbao.common.bean.IMLoginModel;
import com.yunbao.common.bean.SudGameChatImModel;
import com.yunbao.common.event.SudGameSocketImEvent;
import com.yunbao.common.manager.IMLoginManager;
import com.yunbao.common.utils.ToastUtil;
import com.yunbao.common.utils.WordUtil;
import java.util.ArrayList;
import java.util.List;
import cn.rongcloud.rtc.api.RCRTCEngine;
import cn.rongcloud.rtc.api.RCRTCRemoteUser;
import cn.rongcloud.rtc.api.RCRTCRoom;
import cn.rongcloud.rtc.api.RCRTCRoomConfig;
import cn.rongcloud.rtc.api.callback.IRCRTCResultCallback;
import cn.rongcloud.rtc.api.callback.IRCRTCResultDataCallback;
import cn.rongcloud.rtc.api.callback.IRCRTCRoomEventsListener;
import cn.rongcloud.rtc.api.stream.RCRTCInputStream;
import cn.rongcloud.rtc.base.RCRTCRoomType;
import cn.rongcloud.rtc.base.RTCErrorCode;
import io.rong.imlib.IRongCallback;
import io.rong.imlib.IRongCoreCallback;
import io.rong.imlib.IRongCoreEnum;
import io.rong.imlib.RongIMClient;
import io.rong.imlib.chatroom.base.RongChatRoomClient;
import io.rong.imlib.model.Conversation;
import io.rong.imlib.model.Message;
import io.rong.message.TextMessage;
public class GameMicManager {
MeetingCallback mMeetingCallback = null;
private RCRTCRoom mRtcRoom = null;
private String mRoomID = "";
private final IRCRTCRoomEventsListener roomEventsListener = new IRCRTCRoomEventsListener() {
/**
* 房间内用户发布资源
*
* @param rcrtcRemoteUser 远端用户
* @param list 发布的资源
*/
@Override
public void onRemoteUserPublishResource(RCRTCRemoteUser rcrtcRemoteUser, final List<RCRTCInputStream> list) {
subscribeAVStream();
}
@Override
public void onRemoteUserMuteAudio(RCRTCRemoteUser rcrtcRemoteUser, RCRTCInputStream rcrtcInputStream, boolean b) {
}
@Override
public void onRemoteUserMuteVideo(RCRTCRemoteUser rcrtcRemoteUser, RCRTCInputStream rcrtcInputStream, boolean b) {
}
@Override
public void onRemoteUserUnpublishResource(RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {
}
/**
* 用户加入房间
*
* @param rcrtcRemoteUser 远端用户
*/
@Override
public void onUserJoined(final RCRTCRemoteUser rcrtcRemoteUser) {
try {
getView().onUserJoined(rcrtcRemoteUser);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
/**
* 用户离开房间
*
* @param rcrtcRemoteUser 远端用户
*/
@Override
public void onUserLeft(RCRTCRemoteUser rcrtcRemoteUser) {
try {
getView().onUserLeft(rcrtcRemoteUser);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onUserOffline(RCRTCRemoteUser rcrtcRemoteUser) {
}
@Override
public void onPublishLiveStreams(List<RCRTCInputStream> list) {
}
@Override
public void onUnpublishLiveStreams(List<RCRTCInputStream> list) {
}
/**
* 自己退出房间 例如断网退出等
* @param i 状态码
*/
@Override
public void onLeaveRoom(int i) {
}
};
protected MeetingCallback getView() {
if (mMeetingCallback == null) {
throw new IllegalStateException("view is not attached");
} else {
return mMeetingCallback;
}
}
public void attachView(MeetingCallback callback) {
mMeetingCallback = callback;
}
public void detachView() {
mMeetingCallback = null;
}
/**
* 主动订阅远端用户发布的流
* 视频流需要用户设置用于显示载体的videoview
*/
public void subscribeAVStream() {
if (mRtcRoom == null || mRtcRoom.getRemoteUsers() == null) {
return;
}
final List<RCRTCInputStream> inputStreams = new ArrayList<>();
for (final RCRTCRemoteUser remoteUser : mRtcRoom.getRemoteUsers()) {
if (remoteUser.getStreams().size() == 0) {
continue;
}
inputStreams.addAll(remoteUser.getStreams());
}
if (inputStreams.size() == 0) {
return;
}
mRtcRoom.getLocalUser().subscribeStreams(inputStreams, new IRCRTCResultCallback() {
@Override
public void onSuccess() {
try {
getView().onSubscribeSuccess(inputStreams);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onFailed(RTCErrorCode errorCode) {
try {
getView().onSubscribeFailed();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
}
public void unPublishStreams() {
if (mRtcRoom == null) {
return;
}
mRtcRoom.getLocalUser().unpublishStream(RCRTCEngine.getInstance().getDefaultAudioStream(), new IRCRTCResultCallback() {
@Override
public void onSuccess() {
try {
getView().onUnPublishStreamsSuccess();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onFailed(RTCErrorCode errorCode) {
try {
getView().onUnPublishStreamsFailed();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
}
/**
* 发布默认流
*/
public void publishDefaultAVStream() {
if (mRtcRoom == null) {
return;
}
mRtcRoom.getLocalUser().publishStream(RCRTCEngine.getInstance().getDefaultAudioStream(), new IRCRTCResultCallback() {
@Override
public void onSuccess() {
try {
getView().onPublishSuccess();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onFailed(RTCErrorCode rtcErrorCode) {
try {
getView().onPublishFailed();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
}
/**
* 配置rtc sdk
*/
public void config(Context context) {
// RCRTCConfig.Builder configBuilder = RCRTCConfig.Builder.create();
// // 是否硬解码
// configBuilder.enableHardwareDecoder(true);
// // 是否硬编码
// configBuilder.enableHardwareEncoder(true);
//
// // init 需结合 uninit 使用否则有些配置无法重新初始化
// RCRTCEngine.getInstance().unInit();
// RCRTCEngine.getInstance().init(context, configBuilder.build());
// RCRTCVideoStreamConfig.Builder videoConfigBuilder = RCRTCVideoStreamConfig.Builder.create();
// // 设置分辨率
// videoConfigBuilder.setVideoResolution(RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_720_1280);
// // 设置帧率
// videoConfigBuilder.setVideoFps(RCRTCParamsType.RCRTCVideoFps.Fps_30);
// /**
// * 设置最小码率可根据分辨率RCRTCVideoResolution设置
// * {@link RCRTCParamsType.RCRTCVideoResolution)}
// */
// videoConfigBuilder.setMinRate(250);
// /**
// * 设置最大码率可根据分辨率RCRTCVideoResolution设置
// * {@link RCRTCParamsType.RCRTCVideoResolution)}
// */
// videoConfigBuilder.setMaxRate(2200);
// RCRTCEngine.getInstance().getDefaultVideoStream().setVideoConfig(videoConfigBuilder.build());
//打开扬声器
RCRTCEngine.getInstance().enableSpeaker(true);
// 启用耳返功能
// RCRTCEngine.getInstance().getDefaultAudioStream().enableEarMonitoring(true);
RCRTCEngine.getInstance().getDefaultAudioStream().setMicrophoneDisable(false);
}
public void joinRoom(String roomId) {
mRoomID = roomId;
RCRTCRoomConfig roomConfig = RCRTCRoomConfig.Builder.create()
// 根据实际场景选择音视频直播LIVE_AUDIO_VIDEO 或音频直播LIVE_AUDIO
.setRoomType(RCRTCRoomType.MEETING)
.build();
RCRTCEngine.getInstance().joinRoom("v" + roomId, roomConfig, new IRCRTCResultDataCallback<RCRTCRoom>() {
@Override
public void onSuccess(final RCRTCRoom rcrtcRoom) {
GameMicManager.this.mRtcRoom = rcrtcRoom;
// 注册房间回调
rcrtcRoom.registerRoomListener(roomEventsListener);
try {
getView().onJoinRoomSuccess(rcrtcRoom);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onFailed(RTCErrorCode rtcErrorCode) {
try {
getView().onJoinRoomFailed(rtcErrorCode);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
RongChatRoomClient.getInstance().joinChatRoom("v" + roomId, -1, new IRongCoreCallback.OperationCallback() {
@Override
public void onSuccess() {
Log.i("tx", "加入成功");
}
@Override
public void onError(IRongCoreEnum.CoreErrorCode coreErrorCode) {
Log.i("tx", "加入" + "失败" + coreErrorCode);
if (WordUtil.isNewZh()) {
ToastUtil.show("網絡不佳無法連接,請重新進入");
} else {
ToastUtil.show("The network is not connected, please re-enter");
}
}
});
}
public void leaveRoom() {
RCRTCEngine.getInstance().leaveRoom(new IRCRTCResultCallback() {
@Override
public void onFailed(RTCErrorCode rtcErrorCode) {
}
@Override
public void onSuccess() {
}
});
RongChatRoomClient.getInstance().quitChatRoom("v" + mRoomID, new IRongCoreCallback.OperationCallback() {
@Override
public void onSuccess() {
Log.i("tx", "退出成功");
}
@Override
public void onError(IRongCoreEnum.CoreErrorCode coreErrorCode) {
Log.i("tx", "退出" + "" + coreErrorCode);
}
});
}
/**
* 处理游戏房Im消息
*/
public void processingMessage(SudGameSocketImEvent socketImModel) {
List<SudGameSocketImEvent.MsgDTO> msgDTOS = socketImModel.getMsg();
if (msgDTOS.isEmpty()) return;
SudGameSocketImEvent.MsgDTO msgDTO = msgDTOS.get(0);
//正常文字消息
if (TextUtils.equals(msgDTO.getMethod(), "SendMsg")) {
getView().insertItem(new SudGameChatImModel().setNickname(msgDTO.getUname()).setTextMessage(msgDTO.getCt()));
}
}
/**
* 发送聊天信息
*
* @param textMessage
*/
public void sendMessage(String textMessage) {
IMLoginModel loginModel = IMLoginManager.get(CommonAppContext.sInstance.getApplicationContext()).getUserInfo();
SudGameSocketImEvent sudGameSocketImEvent = new SudGameSocketImEvent();
sudGameSocketImEvent.setRetcode("000000");
sudGameSocketImEvent.setRetmsg("ok");
SudGameSocketImEvent.MsgDTO msgDTO = new SudGameSocketImEvent.MsgDTO();
msgDTO.setAction("0")
.setCt(textMessage)
.setEquipment("app")
.setUid(String.valueOf(loginModel.getId()))
.setMethod("SendMsg")
.setUname(loginModel.getUserNicename())
.setRoomnum(mRoomID);
List<SudGameSocketImEvent.MsgDTO> msgDTOS = new ArrayList<>();
msgDTOS.add(msgDTO);
sudGameSocketImEvent.setMsg(msgDTOS);
Conversation.ConversationType conversationType = Conversation.ConversationType.CHATROOM;
TextMessage messageContent = TextMessage.obtain(new Gson().toJson(sudGameSocketImEvent));
Message message = Message.obtain("v" + mRoomID, conversationType, messageContent);
RongIMClient.getInstance().sendMessage(message, null, null, new IRongCallback.ISendMessageCallback() {
@Override
public void onAttached(Message message) {
}
@Override
public void onSuccess(Message message) {
Log.i("tx", "发送成功");
String contentJson = ((TextMessage) message.getContent()).getContent();
Log.e("wewe", contentJson);
SudGameSocketImEvent sudGameSocketImEvent = new Gson().fromJson(contentJson, SudGameSocketImEvent.class);
processingMessage(sudGameSocketImEvent);
}
@Override
public void onError(Message message, RongIMClient.ErrorCode errorCode) {
}
});
}
/**
* activity相关回调
*/
public interface MeetingCallback {
void onJoinRoomSuccess(RCRTCRoom rcrtcRoom);
void onJoinRoomFailed(RTCErrorCode rtcErrorCode);
void onPublishSuccess();
void onPublishFailed();
void onUnPublishStreamsSuccess();
void onUnPublishStreamsFailed();
void onSubscribeSuccess(List<RCRTCInputStream> inputStreamList);
void onSubscribeFailed();
void onUserJoined(RCRTCRemoteUser rcrtcRemoteUser);
void onUserLeft(RCRTCRemoteUser rcrtcRemoteUser);
void insertItem(SudGameChatImModel sudGameChatImModel);
}
}

View File

@ -52,6 +52,10 @@ public class QuickStartGameViewModel extends BaseGameViewModel {
*/ */
public GameViewInfoModel.GameViewRectModel gameViewRectModel; public GameViewInfoModel.GameViewRectModel gameViewRectModel;
public GameViewInfoModel.GameViewRectModel getGameViewRectModel() {
return gameViewRectModel;
}
/** /**
* 游戏的语言代码 * 游戏的语言代码
*/ */

View File

@ -0,0 +1,6 @@
package com.yunbao.common.sud.audio;
public enum AudioEngineUpdateType {
ADD,
DELETE
}

View File

@ -0,0 +1,8 @@
package com.yunbao.common.sud.audio;
import java.nio.ByteBuffer;
public class AudioPCMData {
public ByteBuffer data;
public int dataLength;
}

View File

@ -0,0 +1,34 @@
package com.yunbao.common.sud.audio;
/**
* 语聊房房间状态
*/
public enum AudioRoomState {
DISCONNECTED(0),
CONNECTING(1),
CONNECTED(2);
private int value;
private AudioRoomState(int value) {
this.value = value;
}
public int value() {
return this.value;
}
public static AudioRoomState getZegoRoomState(int value) {
try {
if (DISCONNECTED.value == value) {
return DISCONNECTED;
} else if (CONNECTING.value == value) {
return CONNECTING;
} else {
return CONNECTED.value == value ? CONNECTED : null;
}
} catch (Exception var2) {
throw new RuntimeException("The enumeration cannot be found");
}
}
}

View File

@ -0,0 +1,7 @@
package com.yunbao.common.sud.audio;
public class AudioStream {
public String userID;
public String streamID;
public String extraInfo;
}

View File

@ -0,0 +1,121 @@
package com.yunbao.common.sud.audio;
import android.view.View;
import com.yunbao.common.sud.model.AudioJoinRoomModel;
public interface ISudAudioEngine {
// region 1. 初始化销毁SDK 设置IAudioEventHandler回调
/**
* 设置事件处理器
*
* @param listener 事件处理实例
*/
void setEventListener(ISudAudioEventListener listener);
/**
* 销毁引擎SDK
*/
void destroy();
// endregion
// region 2. 登录房间退出房间
/**
* 加入房间, 登录成功后 默认不推流 默认拉流
*
* @param model roomId
*/
void joinRoom(AudioJoinRoomModel model);
/**
* 离开房间
*/
void leaveRoom();
// endregion
// region 3. 开启推流停止推流
/**
* 开启推流
*/
void startPublishStream();
/**
* 停止推流
*/
void stopPublishStream();
// endregion
// region 4. 开启拉流停止拉流
/**
* 开启拉流进入房间默认订阅拉流
*/
void startSubscribingStream();
/**
* 停止拉流
*/
void stopSubscribingStream();
// endregion
// region 5. 开始音频流监听关闭音频流监听
/**
* 开始音频流监听
*/
void startPCMCapture();
/**
* 关闭音频流监听
*/
void stopPCMCapture();
// endregion
// region 6. 是否使用扬声器作为音频通道
/**
* 切换扬声器作为音频通道
*/
void setAudioRouteToSpeaker(boolean enabled);
// endregion
// region 7. 发送信令
/**
* 发送信令
*
* @param command 信令内容
* @param listener 回调
*/
void sendCommand(String command, SendCommandListener listener);
/**
* 发送指令回调接口
*/
interface SendCommandListener {
void onResult(int value);
}
// endregion
// region 8. 直播接口
/**
* 观众开始拉流
*
* @param streamID
* @param view
* @param mediaViewMode 图像拉伸
*/
void startPlayingStream(String streamID, MediaViewMode mediaViewMode, View view);
/**
* 观众停止拉流
*
* @param streamID
*/
void stopPlayingStream(String streamID);
}

View File

@ -0,0 +1,95 @@
package com.yunbao.common.sud.audio;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.List;
public interface ISudAudioEventListener {
/**
* 捕获本地音量变化, 可用于展示自己说话音浪大小
*
* @param soundLevel 本地音量级别取值范围[0, 100]
*/
void onCapturedSoundLevelUpdate(float soundLevel);
/**
* 捕获远程音流音量变化, 可用于展示远端说话音浪大小
*
* @param soundLevels [userId: 音量]音量取值范围[0, 100]
*/
void onRemoteSoundLevelUpdate(HashMap<String, Float> soundLevels);
/**
* 房间流更新 可用于知道当前推流人数
*
* @param roomId 房间id
* @param type 流更新类型
* @param streamList 变动流列表
* @param extendedData 扩展信息
*/
void onRoomStreamUpdate(String roomId, AudioEngineUpdateType type, List<AudioStream> streamList, JSONObject extendedData);
/**
* 接收自定义指令信息回调
*
* @param fromUserID 用户
* @param command 指令内容
*/
void onRecvCommand(String fromUserID, String command);
/**
* 接收跨房指令信息回调
*
* @param fromRoomID 消息的房间 ID
* @param fromUserID 消息的用户 ID
* @param command 指令内容
*/
void onRecvXRoomCommand(String fromRoomID, String fromUserID, String command);
/**
* 房间内当前在线用户数量回调
*
* @param count 人数
*/
void onRoomOnlineUserCountUpdate(int count);
/**
* 房间状态变化
*
* @param state 状态
* @param errorCode 错误码
* @param extendedData 扩展信息
*/
void onRoomStateUpdate(AudioRoomState state, int errorCode, JSONObject extendedData);
/**
* 监听音频PCM流回调
*
* @param audioPCMData 音频流数据
*/
void onCapturedPCMData(AudioPCMData audioPCMData);
/**
* 观众拉流成功通知
*
* @param streamID
*/
void onPlayingStreamingAdd(String streamID);
/**
* 观众拉流结束通知
*
* @param streamID
*/
void onPlayingStreamingDelete(String streamID);
/**
* 拉流分辨率变更通知
*
* @param streamID 流id
* @param width
* @param height
*/
void onPlayerVideoSizeChanged(String streamID, int width, int height);
}

View File

@ -0,0 +1,7 @@
package com.yunbao.common.sud.audio;
public enum MediaViewMode {
ASPECT_FIT, // 等比缩放可能有黑边
ASPECT_FILL, // 等比缩放填充整个 View可能有部分被裁减
SCALE_TO_FILL; // 填充整个 View图像可能被拉伸
}

View File

@ -0,0 +1,16 @@
package com.yunbao.common.sud.model;
public class AudioJoinRoomModel {
public String userID;
public String userName;
public String roomID;
public String token;
public long timestamp;
public String appId;
}

View File

@ -0,0 +1,108 @@
package com.yunbao.common.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.NinePatch;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Build;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.yunbao.common.manager.IMLoginManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class LoadDian9TuUtilSud {
private static final List<Bitmap> BITMAP_CACHE = new ArrayList<>();//.9图Bitmap缓存
public void loadDian9TuAssets(Context context, View imageView, int position) {
if (TextUtils.isEmpty(IMLoginManager.get(context).getKeyDefaultBubbleUrl())) {
Bitmap bitmap = getImageFromAssetsFile(context, "chat_message_bg.png");
BITMAP_CACHE.add(bitmap);
setNinePathImage(context, imageView, bitmap, position);
} else {
String url = IMLoginManager.get(context).getKeyDefaultBubbleUrl();
LoadDian9Tu(context, imageView, url, 1);
}
}
public void setNinePathImage(Context context, View imageView, Bitmap bitmap, int position) {
if (bitmap == null)
return;
byte[] chunk = bitmap.getNinePatchChunk();
if (NinePatch.isNinePatchChunk(chunk)) {
NinePatchDrawable patchy = new NinePatchDrawable(context.getResources(), bitmap, chunk, NinePatchChunk.deserialize(chunk, position).mPaddings, null);
imageView.setBackground(patchy);
}
}
public void LoadDian9Tu(Context context, View imageView, String imgUrl, int position) {
if (context == null) {
return;
}
if (context instanceof Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (((Activity) context).isDestroyed()) {
return;
}
}
}
Glide.with(context)
.asFile()
.load(imgUrl)
.into(new CustomTarget<File>() {
@Override
public void onResourceReady(@NonNull File resource, @Nullable Transition<? super File> transition) {
try {
FileInputStream is = new FileInputStream(resource);
Bitmap bitmap = BitmapFactory.decodeStream(is);
BITMAP_CACHE.add(bitmap);
setNinePathImage(context, imageView, bitmap, position);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
/**
* 从Assets中读取图片
*
* @param fileName
* @return
*/
private Bitmap getImageFromAssetsFile(Context context, String fileName) {
Bitmap image = null;
AssetManager am = context.getResources().getAssets();
try {
InputStream is = am.open(fileName);
image = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
}

View File

@ -1,4 +1,4 @@
package com.yunbao.live.utils; package com.yunbao.common.utils;
import android.graphics.Rect; import android.graphics.Rect;

View File

@ -0,0 +1,49 @@
package com.yunbao.common.views;
import android.graphics.Color;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.yunbao.common.R;
import com.yunbao.common.bean.SudGameChatImModel;
import com.yunbao.common.utils.LoadDian9TuUtilSud;
public class SudGameChatViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mBg;
private TextView chatMessage;
public SudGameChatViewHolder(@NonNull View itemView) {
super(itemView);
mBg = (LinearLayout) itemView.findViewById(R.id.bg);
chatMessage = itemView.findViewById(R.id.chat_message);
}
/**
* 幸运100%活动
*/
public void sudGameChat(SudGameChatImModel msgModel) {
new LoadDian9TuUtilSud().loadDian9TuAssets(itemView.getContext(), mBg, 1);
StringBuffer buffer = new StringBuffer();
String userName = msgModel.getNickname() + ":";
buffer.append(userName)
.append(" ")
.append(msgModel.getTextMessage());
String msg = buffer.toString();
int unameIndexOf = msg.indexOf(userName);
int unameSize = userName.length();
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(msg);
builder.setSpan(new ForegroundColorSpan(Color.parseColor("#FFBD0D")), unameIndexOf, unameIndexOf + unameSize, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
chatMessage.setText(builder);
}
}

View File

@ -0,0 +1,12 @@
package com.yunbao.common.views;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class SudGameUserListViewHolder extends RecyclerView.ViewHolder {
public SudGameUserListViewHolder(@NonNull View itemView) {
super(itemView);
}
}

View File

@ -1,4 +1,4 @@
package com.yunbao.live.custom; package com.yunbao.common.views;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:topRightRadius="12dp" android:topLeftRadius="12dp"/>
<solid android:color="#E6E9E9E9" />
</shape>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="6dp"/>
<solid android:color="#fff" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp" />
<solid android:color="#CC414141" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:bottomRightRadius="20dp"
android:topRightRadius="20dp" />
<solid android:color="#333333" />
</shape>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="19dp" />
<solid android:color="#B3414141" />
</shape>

View File

@ -1,57 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#201E1A" android:background="#201E1A"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="44dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/game_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="@string/interactive_game_create_room"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="16dp"
android:src="@mipmap/icon_interactive_game_create_room_seats"
android:visibility="gone" />
<ImageView
android:id="@+id/sud_history"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="14dp"
android:src="@mipmap/icon_sud_history_live" />
<TextView
android:id="@+id/exit"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/bg_live_sud_game_back"
android:gravity="center"
android:text="@string/video_exit"
android:textColor="#FFFFFF"
android:textSize="8sp" />
</LinearLayout>
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -61,60 +14,45 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
</RelativeLayout>
<LinearLayout <LinearLayout
android:layout_width="175dp" android:layout_width="150dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_marginStart="15dp" android:layout_marginStart="23dp"
android:layout_marginTop="16dp" android:layout_marginTop="45dp"
android:background="@drawable/bg_live_sud_game_top" android:background="@drawable/bg_live_sud_game_top_new"
android:gravity="center_vertical"> android:gravity="center">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginStart="6dp"
android:scaleType="centerCrop"
android:visibility="gone"
app:riv_oval="true" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_marginStart="4dp" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/interactive_game_create_room_name"
android:textColor="@color/white"
android:textSize="12sp" />
<TextView <TextView
android:id="@+id/room_name" android:id="@+id/room_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:ellipsize="end" android:ellipsize="end"
android:singleLine="true" android:singleLine="true"
android:text="@string/interactive_game_create_room_name"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="12sp" /> android:textSize="14sp"
</LinearLayout> android:textStyle="bold" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_marginTop="4dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/interactive_game_create_room_number" android:text="ID:"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="12sp" /> android:textSize="12sp" />
@ -122,12 +60,96 @@
android:id="@+id/room_number" android:id="@+id/room_number"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/interactive_game_create_room_number"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="49dp"
android:layout_marginEnd="20dp"
android:gravity="center_vertical">
<ImageView
android:id="@+id/sud_history"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="14dp"
android:src="@mipmap/icon_sud_history_live_new" />
<TextView
android:id="@+id/exit"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/bg_live_sud_game_back_new"
android:gravity="center"
android:text="@string/video_exit"
android:textColor="#FFFFFF"
android:textSize="8sp" />
</LinearLayout>
<LinearLayout
android:layout_width="137dp"
android:layout_height="34dp"
android:layout_gravity="bottom"
android:layout_marginStart="12dp"
android:layout_marginBottom="35dp">
<TextView
android:id="@+id/game_review_input"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_live_sud_game_bottom_input"
android:gravity="center"
android:text="@string/game_review_input"
android:textColor="@color/white"
android:textSize="14sp" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="12dp"
android:layout_marginBottom="35dp"
android:animateLayoutChanges="true">
<ImageView
android:id="@+id/game_close_wheat"
android:layout_width="34dp"
android:layout_height="34dp"
android:layout_marginEnd="20dp"
android:src="@mipmap/icon_game_close_wheat" />
<ImageView
android:id="@+id/game_seat"
android:layout_width="34dp"
android:layout_height="34dp"
android:src="@mipmap/icon_game_seat" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/chat_list"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_gravity="bottom"
android:layout_marginBottom="75dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/user_list"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="100dp"
android:layout_marginBottom="75dp" />
</FrameLayout>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="51dp"
android:background="@drawable/background_sud_game_input">
<EditText
android:id="@+id/text_message"
android:layout_width="260dp"
android:layout_height="38dp"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:background="@drawable/background_sud_game_input_edit_text"
android:hint="@string/live_say_something"
android:paddingRight="10dp"
android:textColorHint="@color/gray3" />
<TextView
android:id="@+id/send"
android:layout_width="60dp"
android:layout_height="38dp"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="20dp"
android:background="@mipmap/icon_send_game"
android:gravity="center"
android:text="@string/send"
android:textColor="@color/white"
android:textSize="16sp" />
</FrameLayout>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="283dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp">
<TextView
android:id="@+id/chat_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="9dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:gravity="center_vertical"
android:textColor="#FFFFFF"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<ImageView
android:id="@+id/vacancy_sud_game"
android:layout_width="34dp"
android:layout_height="34dp"
android:layout_marginStart="12dp"
android:src="@mipmap/icon_vacancy_sud_game" />
<FrameLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:visibility="gone">
</FrameLayout>
</LinearLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1428,4 +1428,5 @@ Limited ride And limited avatar frame</string>
<string name="battlepass_exchange_buy_max">The quantity of goods exchanged has reached the upper limit</string> <string name="battlepass_exchange_buy_max">The quantity of goods exchanged has reached the upper limit</string>
<string name="battlepass_zl_get">Successfully opened</string> <string name="battlepass_zl_get">Successfully opened</string>
<string name="battlepass_buy_max">You have purchased the BattlePass</string> <string name="battlepass_buy_max">You have purchased the BattlePass</string>
<string name="game_review_input">評論</string>
</resources> </resources>

View File

@ -24,9 +24,7 @@ import com.opensource.svgaplayer.SVGADrawable;
import com.opensource.svgaplayer.SVGAImageView; import com.opensource.svgaplayer.SVGAImageView;
import com.opensource.svgaplayer.SVGAParser; import com.opensource.svgaplayer.SVGAParser;
import com.opensource.svgaplayer.SVGAVideoEntity; import com.opensource.svgaplayer.SVGAVideoEntity;
import com.yunbao.common.CommonAppConfig;
import com.yunbao.common.Constants; import com.yunbao.common.Constants;
import com.yunbao.common.bean.LevelBean;
import com.yunbao.common.dialog.AbsDialogFragment; import com.yunbao.common.dialog.AbsDialogFragment;
import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.glide.ImgLoader;
import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpCallback;
@ -36,7 +34,7 @@ import com.yunbao.common.utils.SVGAViewUtils;
import com.yunbao.live.R; import com.yunbao.live.R;
import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveActivity;
import com.yunbao.live.bean.HotBean; import com.yunbao.live.bean.HotBean;
import com.yunbao.live.custom.TopGradual; import com.yunbao.common.views.TopGradual;
import com.yunbao.common.http.LiveHttpUtil; import com.yunbao.common.http.LiveHttpUtil;
import com.yunbao.live.utils.LiveTextRender; import com.yunbao.live.utils.LiveTextRender;

View File

@ -19,6 +19,7 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition; import com.bumptech.glide.request.transition.Transition;
import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMLoginManager;
import com.yunbao.common.utils.NinePatchChunk;
import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveActivity;
import java.io.File; import java.io.File;

View File

@ -160,7 +160,7 @@ import com.yunbao.live.bean.LiveWishlistBean;
import com.yunbao.live.bean.WishlistItemModel; import com.yunbao.live.bean.WishlistItemModel;
import com.yunbao.live.custom.LiveLightView; import com.yunbao.live.custom.LiveLightView;
import com.yunbao.live.custom.RightGradual; import com.yunbao.live.custom.RightGradual;
import com.yunbao.live.custom.TopGradual; import com.yunbao.common.views.TopGradual;
import com.yunbao.live.dialog.GiftWallDialog; import com.yunbao.live.dialog.GiftWallDialog;
import com.yunbao.live.dialog.LiveContactDetailsSendGiftDialog; import com.yunbao.live.dialog.LiveContactDetailsSendGiftDialog;
import com.yunbao.live.dialog.LiveFaceUnityDialogFragment; import com.yunbao.live.dialog.LiveFaceUnityDialogFragment;

View File

@ -67,7 +67,7 @@ import com.yunbao.live.adapter.YouLikeMessageAdapter;
import com.yunbao.live.bean.SearchUserBean; import com.yunbao.live.bean.SearchUserBean;
import com.yunbao.live.bean.SystemMessageBean; import com.yunbao.live.bean.SystemMessageBean;
import com.yunbao.live.bean.YouLikeBean; import com.yunbao.live.bean.YouLikeBean;
import com.yunbao.live.custom.TopGradual; import com.yunbao.common.views.TopGradual;
import com.yunbao.live.http.ImHttpConsts; import com.yunbao.live.http.ImHttpConsts;
import com.yunbao.live.http.ImHttpUtil; import com.yunbao.live.http.ImHttpUtil;