2025-10-28 19:13:52 +08:00
|
|
|
package com.xscm.modulemain;
|
|
|
|
|
|
|
|
|
|
import static com.xscm.moduleutil.base.CommonAppContext.postDelayed;
|
|
|
|
|
|
|
|
|
|
import android.animation.Animator;
|
|
|
|
|
import android.animation.AnimatorListenerAdapter;
|
|
|
|
|
import android.animation.ObjectAnimator;
|
|
|
|
|
import android.app.Activity;
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.res.Configuration;
|
|
|
|
|
import android.content.res.Resources;
|
|
|
|
|
import android.media.MediaPlayer;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.text.Spannable;
|
|
|
|
|
import android.text.SpannableStringBuilder;
|
|
|
|
|
import android.text.style.ForegroundColorSpan;
|
|
|
|
|
import android.util.DisplayMetrics;
|
|
|
|
|
import android.view.Gravity;
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
import android.view.animation.AccelerateInterpolator;
|
|
|
|
|
import android.view.animation.Animation;
|
|
|
|
|
import android.view.animation.DecelerateInterpolator;
|
|
|
|
|
import android.view.animation.TranslateAnimation;
|
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
import android.widget.ImageView;
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
import androidx.annotation.Nullable;
|
2025-10-28 19:13:52 +08:00
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
|
import androidx.databinding.ViewDataBinding;
|
|
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
import com.blankj.utilcode.util.ActivityUtils;
|
|
|
|
|
import com.blankj.utilcode.util.GsonUtils;
|
2025-10-28 19:13:52 +08:00
|
|
|
import com.blankj.utilcode.util.LogUtils;
|
|
|
|
|
import com.blankj.utilcode.util.ToastUtils;
|
|
|
|
|
import com.tencent.imsdk.v2.V2TIMSDKListener;
|
|
|
|
|
import com.tencent.imsdk.v2.V2TIMValueCallback;
|
|
|
|
|
import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo;
|
2025-11-20 09:40:53 +08:00
|
|
|
import com.xscm.modulemain.activity.WebViewActivity;
|
|
|
|
|
import com.xscm.modulemain.activity.main.activity.MainActivity;
|
2025-12-04 20:56:30 +08:00
|
|
|
import com.xscm.modulemain.activity.room.activity.RoomActivity;
|
2025-11-24 18:48:14 +08:00
|
|
|
import com.xscm.modulemain.activity.user.activity.HeartCpActivity;
|
2025-10-28 19:13:52 +08:00
|
|
|
import com.xscm.modulemain.manager.RoomManager;
|
2025-11-20 09:40:53 +08:00
|
|
|
import com.xscm.moduleutil.BaseEvent;
|
|
|
|
|
import com.xscm.moduleutil.R;
|
2025-10-28 19:13:52 +08:00
|
|
|
import com.xscm.moduleutil.activity.BaseAppCompatActivity;
|
|
|
|
|
import com.xscm.moduleutil.activity.IPresenter;
|
|
|
|
|
import com.xscm.moduleutil.activity.IView;
|
|
|
|
|
import com.xscm.moduleutil.base.CommonAppContext;
|
2025-11-18 18:28:16 +08:00
|
|
|
import com.xscm.moduleutil.base.WebUrlConstants;
|
2025-11-20 09:40:53 +08:00
|
|
|
import com.xscm.moduleutil.bean.RoomGiftData;
|
|
|
|
|
import com.xscm.moduleutil.bean.RoomMessageEvent;
|
2025-10-28 19:13:52 +08:00
|
|
|
import com.xscm.moduleutil.bean.UserBean;
|
|
|
|
|
import com.xscm.moduleutil.bean.XLHBean;
|
|
|
|
|
import com.xscm.moduleutil.dialog.ConfirmDialog;
|
|
|
|
|
import com.xscm.moduleutil.event.HourlyBean;
|
|
|
|
|
import com.xscm.moduleutil.event.MqttBean;
|
|
|
|
|
import com.xscm.moduleutil.event.RedBean;
|
|
|
|
|
import com.xscm.moduleutil.event.UnreadCountEvent;
|
2025-11-20 09:40:53 +08:00
|
|
|
import com.xscm.moduleutil.http.BaseObserver;
|
2025-10-28 19:13:52 +08:00
|
|
|
import com.xscm.moduleutil.http.RetrofitClient;
|
2025-11-20 09:40:53 +08:00
|
|
|
import com.xscm.moduleutil.listener.CPListener;
|
|
|
|
|
import com.xscm.moduleutil.listener.MessageListenerSingleton;
|
2025-11-14 17:38:30 +08:00
|
|
|
import com.xscm.moduleutil.utils.ClickUtils;
|
2025-10-28 19:13:52 +08:00
|
|
|
import com.xscm.moduleutil.utils.ImageUtils;
|
|
|
|
|
import com.xscm.moduleutil.utils.LanguageUtil;
|
|
|
|
|
import com.tencent.imsdk.v2.V2TIMManager;
|
|
|
|
|
import com.tencent.imsdk.v2.V2TIMUserFullInfo;
|
|
|
|
|
import com.tencent.qcloud.tuicore.TUILogin;
|
|
|
|
|
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
|
|
|
|
|
import com.xscm.moduleutil.utils.SpUtil;
|
|
|
|
|
import com.xscm.moduleutil.utils.SystemUtils;
|
|
|
|
|
|
|
|
|
|
import org.greenrobot.eventbus.EventBus;
|
|
|
|
|
import org.greenrobot.eventbus.Subscribe;
|
|
|
|
|
import org.greenrobot.eventbus.ThreadMode;
|
2025-11-20 09:40:53 +08:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
2025-10-28 19:13:52 +08:00
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
import java.nio.charset.StandardCharsets;
|
2025-10-28 19:13:52 +08:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
2025-12-04 20:56:30 +08:00
|
|
|
import java.util.Objects;
|
2025-11-20 09:40:53 +08:00
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
|
|
import io.reactivex.disposables.Disposable;
|
2025-10-28 19:13:52 +08:00
|
|
|
|
|
|
|
|
public abstract class BaseMvpActivity<P extends IPresenter, VDB extends ViewDataBinding> extends BaseAppCompatActivity<VDB> implements
|
|
|
|
|
IView<Activity> {
|
|
|
|
|
|
|
|
|
|
protected P MvpPre;
|
2025-11-20 09:40:53 +08:00
|
|
|
private ConfirmDialog confirmDialog;
|
2025-10-28 19:13:52 +08:00
|
|
|
|
|
|
|
|
protected abstract P bindPresenter();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void doDone() {
|
|
|
|
|
super.doDone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void initView() {
|
|
|
|
|
MvpPre = bindPresenter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void showLoadings() {
|
2025-11-14 17:38:30 +08:00
|
|
|
showLoading();
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void showLoadings(String content) {
|
2025-11-14 17:38:30 +08:00
|
|
|
showLoading(content);
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void disLoadings() {
|
2025-11-14 17:38:30 +08:00
|
|
|
disLoading();
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
RetrofitClient.getInstance ().CpListener(new CPListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceiveMsg(@NotNull RoomMessageEvent roomMessageEvent) {
|
|
|
|
|
cpReceiver(roomMessageEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onSendCpMsg(@NotNull RoomGiftData gitData) {
|
|
|
|
|
cpMsg(gitData);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-28 19:13:52 +08:00
|
|
|
@Override
|
|
|
|
|
protected void onDestroy() {
|
2025-11-14 17:38:30 +08:00
|
|
|
ClickUtils.clearAllClickRecords();
|
2025-10-28 19:13:52 +08:00
|
|
|
// 清理MQTT相关资源
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
mqttMessageQueue.clear();
|
|
|
|
|
isMqttPlaying = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 清理XLH相关资源
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
xlhMessageQueue.clear();
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移除当前显示的视图
|
|
|
|
|
try {
|
|
|
|
|
if (currentMqttView != null && currentMqttView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentMqttView.getParent();
|
|
|
|
|
parent.removeView(currentMqttView);
|
|
|
|
|
}
|
|
|
|
|
currentMqttView = null;
|
|
|
|
|
|
|
|
|
|
if (currentXlhView != null && currentXlhView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentXlhView.getParent();
|
|
|
|
|
parent.removeView(currentXlhView);
|
|
|
|
|
}
|
|
|
|
|
currentXlhView = null;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("清理飘屏视图失败", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (MvpPre != null) {
|
|
|
|
|
try {
|
|
|
|
|
MvpPre.detachView();
|
2025-11-14 17:38:30 +08:00
|
|
|
} catch (Exception e) {
|
2025-10-28 19:13:52 +08:00
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
super.onDestroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Activity getSelfActivity() {
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void attachBaseContext(Context newBase) {
|
|
|
|
|
super.attachBaseContext(LanguageUtil.attachBaseContext(newBase));
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
|
|
|
|
|
public void cpMsg(RoomGiftData event) {
|
|
|
|
|
String cpTypeJson = GsonUtils.toJson(event.getCp_type());
|
|
|
|
|
if (event.getCp_type().getCp_type() == 1) {
|
|
|
|
|
|
|
|
|
|
if (event.getGift_user_data()!=null && event.getGift_user_data().size()>0){
|
|
|
|
|
for (int i = 0; i <event.getGift_user_data().size(); i++)
|
|
|
|
|
// 创建自定义消息
|
|
|
|
|
MessageListenerSingleton.getInstance().sendCustomC2CMessage(130,cpTypeJson,
|
|
|
|
|
event.getGift_user_data().get(i).getUser_id()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}else if (event.getCp_type().getCp_type() == 2) {
|
|
|
|
|
if (event.getGift_user_data()!=null && event.getGift_user_data().size()>0){
|
|
|
|
|
for (int i = 0; i < event.getGift_user_data().size(); i++)
|
|
|
|
|
// 创建自定义消息
|
|
|
|
|
MessageListenerSingleton.getInstance().sendCustomC2CMessage(131,cpTypeJson,
|
|
|
|
|
event.getGift_user_data().get(i).getUser_id()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void cpReceiver(BaseEvent event) {
|
|
|
|
|
String a = ActivityUtils.getTopActivity().getLocalClassName();
|
|
|
|
|
if (event instanceof RoomMessageEvent) {
|
|
|
|
|
com.xscm.moduleutil.bean.RoomGiftData.CpType text = GsonUtils.fromJson(((RoomMessageEvent) event).getText().getText().toString(),com.xscm.moduleutil.bean.RoomGiftData.CpType.class);
|
|
|
|
|
if (text.getCp_type() == 1) {
|
2025-11-24 18:48:14 +08:00
|
|
|
queren1(1,text.getText1(),text.getGift_id()+"",((RoomMessageEvent) event).getText().getFromUserInfo().getUser_id()+"",((RoomMessageEvent) event).getRoomId());
|
2025-11-20 09:40:53 +08:00
|
|
|
}else if (text.getCp_type() == 2) {
|
|
|
|
|
queren1(2,text.getText1(),text.getGift_id()+"",((RoomMessageEvent) event).getText().getFromUserInfo().getUser_id()+"",((RoomMessageEvent) event).getRoomId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: 2025/11/19 登录腾讯
|
2025-10-28 19:13:52 +08:00
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
public void logOutEvent(UserBean userBean) {
|
|
|
|
|
// 在用户 UI 点击登录的时候调用
|
|
|
|
|
TUILogin.login(getBaseContext(), CommonAppContext.getInstance().getCurrentEnvironment().getSdkAppId(), "u" + userBean.getUser_id(), userBean.getTencent_im(), new TUICallback() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onError(final int code, final String desc) {
|
|
|
|
|
LogUtils.e("@@@1", code, "描述:", desc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onSuccess() {
|
|
|
|
|
LogUtils.e("@@@", "成功");
|
|
|
|
|
V2TIMManager.getConversationManager().getTotalUnreadMessageCount(new V2TIMValueCallback<Long>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onSuccess(Long aLong) {
|
|
|
|
|
// 通知未读数变化
|
2025-11-14 17:38:30 +08:00
|
|
|
UnreadCountEvent event = CommonAppContext.getInstance().unreadCountEvent;
|
|
|
|
|
if (event == null) {
|
|
|
|
|
event = new UnreadCountEvent();
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
event.setALong(aLong);
|
|
|
|
|
// 使用EventBus通知
|
|
|
|
|
CommonAppContext.getInstance().setUnreadCountEvent(event);
|
|
|
|
|
EventBus.getDefault().post(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onError(int code, String desc) {
|
|
|
|
|
// 错误处理
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
//initLocation();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// V2TIMManager.getInstance().addIMSDKListener(imSdkListener);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private final V2TIMSDKListener imSdkListener = new V2TIMSDKListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onConnecting() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onConnectSuccess() {//重连成功
|
2025-11-14 17:38:30 +08:00
|
|
|
if (CommonAppContext.getInstance().playId != null) {
|
2025-10-28 19:13:52 +08:00
|
|
|
LogUtils.e("@@@", "重连成功");
|
2025-11-14 17:38:30 +08:00
|
|
|
LogUtils.e("@@@", "" + CommonAppContext.getInstance().playId);
|
2025-12-02 14:11:40 +08:00
|
|
|
// RetrofitClient.getInstance().roomUserReconnect(CommonAppContext.getInstance().playId);
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onConnectFailed(int code, String error) {
|
|
|
|
|
LogUtils.e("@@@", "断开连接");
|
2025-11-14 17:38:30 +08:00
|
|
|
CommonAppContext.getInstance().onConnectFailed = true;
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onKickedOffline() {
|
|
|
|
|
// queren1();
|
2025-11-14 17:38:30 +08:00
|
|
|
if (CommonAppContext.getInstance().playId != null) {
|
2025-10-28 19:13:52 +08:00
|
|
|
ToastUtils.showShort("您的账号已被挤下线");
|
|
|
|
|
try {
|
|
|
|
|
CommonAppContext.getInstance().clearLoginInfo();
|
|
|
|
|
} catch (ClassNotFoundException e) {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onUserSigExpired() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onSelfInfoUpdated(V2TIMUserFullInfo info) {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
private void queren1(int type,String content,String giftid,String userId,String roomId) {
|
2025-10-28 19:13:52 +08:00
|
|
|
// 创建并显示确认对话框
|
2025-11-20 09:40:53 +08:00
|
|
|
new ConfirmDialog(ActivityUtils.getTopActivity(),
|
|
|
|
|
type==1?"心动信号":"缘定三生 此刻同心",
|
|
|
|
|
content,
|
|
|
|
|
type==1?"回赠同心锁":"进入心动空间",
|
|
|
|
|
type==1?"再想想":"我知道了",
|
2025-10-28 19:13:52 +08:00
|
|
|
v -> {
|
2025-11-20 09:40:53 +08:00
|
|
|
if (type==1) {
|
|
|
|
|
// 点击“确认”按钮时执行删除操作
|
|
|
|
|
RetrofitClient.getInstance().cpGiveGift(userId, giftid, roomId, new BaseObserver<RoomGiftData>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onSubscribe(Disposable d) {
|
2025-10-28 19:13:52 +08:00
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
}
|
2025-10-28 19:13:52 +08:00
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
@Override
|
|
|
|
|
public void onNext(RoomGiftData roomGiftData) {
|
|
|
|
|
if (roomGiftData.getCp_type() != null) {
|
|
|
|
|
if (roomGiftData.getCp_type().getCp_type()==2){
|
|
|
|
|
queren1(2,roomGiftData.getCp_type().getText(),"",SpUtil.getUserId()+"","");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2025-11-24 18:48:14 +08:00
|
|
|
}else {
|
|
|
|
|
int userids= Integer.parseInt(userId);
|
|
|
|
|
Intent intent = new Intent(ActivityUtils.getTopActivity(), HeartCpActivity.class);
|
|
|
|
|
intent.putExtra("userId",userids);
|
|
|
|
|
startActivity(intent);
|
2025-11-20 09:40:53 +08:00
|
|
|
}
|
2025-10-28 19:13:52 +08:00
|
|
|
},
|
|
|
|
|
v -> {
|
|
|
|
|
// 点击“取消”按钮时什么都不做
|
|
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
}, false,0).show();
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Resources getResources() {
|
|
|
|
|
Resources resources = super.getResources();
|
|
|
|
|
if (resources != null) {
|
|
|
|
|
Configuration configuration = resources.getConfiguration();
|
|
|
|
|
if (configuration != null) {
|
|
|
|
|
// 设置字体缩放比例不随系统变化
|
|
|
|
|
configuration.fontScale = 1.0f; // 1.0f表示默认大小
|
|
|
|
|
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return resources;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 礼物特效
|
|
|
|
|
/// 礼物特效
|
|
|
|
|
// 在类中添加以下成员变量
|
|
|
|
|
private final List<MqttBean.ListBean> mqttMessageQueue = new ArrayList<>(); // MQTT消息队列
|
|
|
|
|
private final List<XLHBean> xlhMessageQueue = new ArrayList<>(); // XLH消息队列
|
|
|
|
|
private final List<RedBean> redMessageQueue = new ArrayList<>(); // 红包队列
|
|
|
|
|
private boolean isMqttPlaying = false; // MQTT播放状态标志
|
|
|
|
|
private boolean isXlhPlaying = false; // XLH播放状态标志
|
|
|
|
|
private boolean isRedPlaying = false; // XLH播放状态标志
|
|
|
|
|
private final Object mqttQueueLock = new Object(); // MQTT队列同步锁
|
|
|
|
|
private final Object xlhQueueLock = new Object(); // XLH队列同步锁
|
|
|
|
|
private final Object RedQueueLock = new Object(); // XLH队列同步锁
|
|
|
|
|
private View currentMqttView = null; // 当前正在播放的MQTT视图
|
|
|
|
|
private View currentXlhView = null; // 当前正在播放的XLH视图
|
|
|
|
|
private View currentRedView = null; // 当前正在播放的XLH视图
|
|
|
|
|
|
|
|
|
|
private final List<HourlyBean> hourlyMessageQueue = new ArrayList<>(); // 小时榜消息队列
|
|
|
|
|
private final Map<Integer, View> currentHourlyViews = new HashMap<>(); // 当前显示的小时榜视图
|
|
|
|
|
private final Object hourlyQueueLock = new Object(); // 小时榜队列同步锁
|
|
|
|
|
private boolean isHourlyProcessing = false; // 小时榜处理状态标志
|
|
|
|
|
|
2025-11-20 09:40:53 +08:00
|
|
|
// TODO: 2025/11/19 收到小时榜
|
2025-10-28 19:13:52 +08:00
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
public void onMessageReceived(List<HourlyBean> hourlyBean) {
|
|
|
|
|
LogUtils.e("收到小时榜", hourlyBean);
|
|
|
|
|
if (hourlyBean == null) return;
|
|
|
|
|
if (SpUtil.getFloatingScreen() == 1) {
|
|
|
|
|
synchronized (hourlyQueueLock) {
|
|
|
|
|
hourlyMessageQueue.addAll(hourlyBean);
|
|
|
|
|
if (!isHourlyProcessing) {
|
|
|
|
|
isHourlyProcessing = true;
|
|
|
|
|
processHourlyMessages();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
hourlyMessageQueue.clear();
|
|
|
|
|
clearAllHourlyViews();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processHourlyMessages() {
|
|
|
|
|
List<HourlyBean> messagesToProcess;
|
|
|
|
|
synchronized (hourlyQueueLock) {
|
|
|
|
|
if (hourlyMessageQueue.isEmpty()) {
|
|
|
|
|
isHourlyProcessing = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 每次只处理1条数据
|
|
|
|
|
messagesToProcess = new ArrayList<>();
|
|
|
|
|
messagesToProcess.add(hourlyMessageQueue.remove(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 只展示一条数据
|
|
|
|
|
HourlyBean bean = messagesToProcess.get(0);
|
|
|
|
|
showHourlyFloatingMessage(bean, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showHourlyFloatingMessage(HourlyBean hourlyBean, int positionIndex) {
|
|
|
|
|
try {
|
|
|
|
|
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
|
|
|
|
|
|
|
|
|
|
// 创建新的视图
|
|
|
|
|
View hourlyView = LayoutInflater.from(this).inflate(com.xscm.moduleutil.R.layout.item_hourly_floating, null);
|
|
|
|
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
|
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
|
|
|
|
|
// 设置固定的垂直位置
|
|
|
|
|
int baseMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 70);
|
|
|
|
|
layoutParams.topMargin = baseMargin;
|
|
|
|
|
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
|
|
|
|
hourlyView.setLayoutParams(layoutParams);
|
|
|
|
|
|
|
|
|
|
decorView.addView(hourlyView);
|
|
|
|
|
|
|
|
|
|
// 保存视图引用
|
|
|
|
|
currentHourlyViews.put(positionIndex, hourlyView);
|
|
|
|
|
|
|
|
|
|
// 更新视图数据
|
|
|
|
|
updateHourlyFloatingViewData(hourlyView, hourlyBean);
|
|
|
|
|
|
|
|
|
|
// 根据类型获取展示时间
|
|
|
|
|
long displayDuration = getDisplayDurationByType(Integer.parseInt(hourlyBean.getRank_number()));
|
|
|
|
|
|
|
|
|
|
// 启动动画
|
|
|
|
|
resetAndStartHourlyAnimation(hourlyView, displayDuration, () -> {
|
|
|
|
|
// 动画结束后清理视图
|
|
|
|
|
if (hourlyView.getParent() != null) {
|
|
|
|
|
decorView.removeView(hourlyView);
|
|
|
|
|
}
|
|
|
|
|
currentHourlyViews.remove(positionIndex);
|
|
|
|
|
|
|
|
|
|
// 检查是否还有更多消息需要处理
|
|
|
|
|
synchronized (hourlyQueueLock) {
|
|
|
|
|
if (hourlyMessageQueue.isEmpty()) {
|
|
|
|
|
isHourlyProcessing = false;
|
|
|
|
|
} else {
|
|
|
|
|
// 当前视图消失后处理下一条消息
|
|
|
|
|
processHourlyMessages();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("显示小时榜飘屏失败", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private long getDisplayDurationByType(int type) {
|
|
|
|
|
// 根据不同类型设置不同的展示时间(毫秒)
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 1: // 第一名
|
|
|
|
|
return 5000; // 5秒
|
|
|
|
|
case 2: // 第二名
|
|
|
|
|
return 4000; // 4秒
|
|
|
|
|
case 3: // 第三名
|
|
|
|
|
return 3000; // 3秒
|
|
|
|
|
default:
|
|
|
|
|
return 3000; // 默认3秒
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateHourlyFloatingViewData(View view, HourlyBean hourlyBean) {
|
|
|
|
|
TextView tvName = view.findViewById(com.xscm.moduleutil.R.id.tv_name);
|
|
|
|
|
ImageView ivAvatar = view.findViewById(com.xscm.moduleutil.R.id.im_h_t);
|
|
|
|
|
|
|
|
|
|
if (hourlyBean != null) {
|
|
|
|
|
// 根据排名设置不同的显示
|
|
|
|
|
switch (hourlyBean.getRank_number()) {
|
|
|
|
|
case "1":
|
|
|
|
|
// tvName.setText("新科状元! ["+hourlyBean.getRoom_name()+"] 独占鳌头!");
|
|
|
|
|
setColoredText(tvName, "新科状元! [", hourlyBean.getRoom_name(), "] 独占鳌头!", com.xscm.moduleutil.R.color.color_FFFA63);
|
|
|
|
|
ivAvatar.setImageResource(com.xscm.moduleutil.R.mipmap.hourl_top1);
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
// tvName.setText("金榜榜眼! ["+hourlyBean.getRoom_name()+"] 才气逼人!");
|
|
|
|
|
setColoredText(tvName, "金榜榜眼! [", hourlyBean.getRoom_name(), "] 才气逼人!", com.xscm.moduleutil.R.color.color_FFFA63);
|
|
|
|
|
|
|
|
|
|
ivAvatar.setImageResource(com.xscm.moduleutil.R.mipmap.hourl_top2);
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
setColoredText(tvName, "风采探花! [", hourlyBean.getRoom_name(), "] 实力绽放!", com.xscm.moduleutil.R.color.color_1FFFE5);
|
|
|
|
|
// tvName.setText("风采探花! ["+hourlyBean.getRoom_name()+"] 实力绽放!");
|
|
|
|
|
|
|
|
|
|
ivAvatar.setImageResource(com.xscm.moduleutil.R.mipmap.hourl_top3);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
tvName.setVisibility(View.GONE);
|
|
|
|
|
ivAvatar.setVisibility(View.GONE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置带颜色的文本
|
|
|
|
|
// 设置带颜色的文本
|
|
|
|
|
private void setColoredText(TextView textView, String prefix, String roomName, String suffix, int colorRes) {
|
|
|
|
|
String fullText = prefix + roomName + suffix;
|
|
|
|
|
SpannableStringBuilder builder = new SpannableStringBuilder(fullText);
|
|
|
|
|
|
|
|
|
|
// 先为整个文本设置白色
|
|
|
|
|
builder.setSpan(
|
|
|
|
|
new ForegroundColorSpan(ContextCompat.getColor(this, R.color.white)),
|
|
|
|
|
0,
|
|
|
|
|
fullText.length(),
|
|
|
|
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 查找房间名在文本中的位置
|
|
|
|
|
int start = fullText.indexOf("[");
|
|
|
|
|
int end = fullText.indexOf("]") + 1;
|
|
|
|
|
|
|
|
|
|
if (start >= 0 && end > start) {
|
|
|
|
|
// 为房间名部分设置指定颜色
|
|
|
|
|
builder.setSpan(
|
|
|
|
|
new ForegroundColorSpan(ContextCompat.getColor(this, colorRes)),
|
|
|
|
|
start,
|
|
|
|
|
end,
|
|
|
|
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
textView.setText(builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void resetAndStartHourlyAnimation(View view, long displayDuration, Runnable onAnimationEnd) {
|
|
|
|
|
try {
|
|
|
|
|
int screenWidth = getScreenWidth();
|
|
|
|
|
// 设置初始位置:在屏幕右侧外部
|
|
|
|
|
view.setTranslationX(screenWidth);
|
|
|
|
|
|
|
|
|
|
// 进入动画
|
|
|
|
|
ObjectAnimator enterAnimator = ObjectAnimator.ofFloat(view, "translationX", screenWidth, 0f);
|
|
|
|
|
enterAnimator.setDuration(500);
|
|
|
|
|
enterAnimator.setInterpolator(new DecelerateInterpolator());
|
|
|
|
|
enterAnimator.start();
|
|
|
|
|
|
|
|
|
|
// 停留后退出动画
|
|
|
|
|
view.postDelayed(() -> {
|
|
|
|
|
try {
|
|
|
|
|
ObjectAnimator exitAnimator = ObjectAnimator.ofFloat(view, "translationX", 0f, -screenWidth);
|
|
|
|
|
exitAnimator.setDuration(500);
|
|
|
|
|
exitAnimator.setInterpolator(new AccelerateInterpolator());
|
|
|
|
|
exitAnimator.addListener(new AnimatorListenerAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationCancel(Animator animation) {
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
exitAnimator.start();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("小时榜退出动画执行失败", e);
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
}, displayDuration); // 根据类型设置的展示时间
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("小时榜动画启动失败", e);
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void clearAllHourlyViews() {
|
|
|
|
|
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
|
|
|
|
|
for (View view : currentHourlyViews.values()) {
|
|
|
|
|
if (view.getParent() != null) {
|
|
|
|
|
decorView.removeView(view);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentHourlyViews.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 礼物特效 - MQTT消息处理
|
|
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
public void onMessageReceived(MqttBean mqttBean) {
|
|
|
|
|
LogUtils.e("收到MQTT", mqttBean);
|
|
|
|
|
if (mqttBean == null) return;
|
|
|
|
|
if (SpUtil.getFloatingScreen() == 1) {
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
|
|
|
|
|
mqttMessageQueue.addAll(mqttBean.getList());
|
|
|
|
|
// if (!isMqttPlaying) {
|
|
|
|
|
// isMqttPlaying = true;
|
|
|
|
|
processNextMqttMessage();
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
mqttMessageQueue.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// XLH消息处理
|
|
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
public void onEvent(XLHBean event) {
|
|
|
|
|
LogUtils.e("收到XLH", event);
|
|
|
|
|
if (event == null) return;
|
2025-11-14 17:38:30 +08:00
|
|
|
if (event.getText() == null || event.getText().isEmpty()) return;
|
2025-10-28 19:13:52 +08:00
|
|
|
if (SpUtil.getFloatingScreen() == 1) {
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
xlhMessageQueue.add(event);
|
|
|
|
|
if (!isXlhPlaying) {
|
|
|
|
|
isXlhPlaying = true;
|
|
|
|
|
processNextXlhMessage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
xlhMessageQueue.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
2025-11-14 17:38:30 +08:00
|
|
|
public void onEvent(RedBean event) {
|
2025-10-28 19:13:52 +08:00
|
|
|
LogUtils.e("收到红包", event);
|
2025-11-14 17:38:30 +08:00
|
|
|
if (event == null) return;
|
|
|
|
|
if (SpUtil.getFloatingScreen() == 1) {
|
2025-10-28 19:13:52 +08:00
|
|
|
|
|
|
|
|
synchronized (RedQueueLock) {
|
|
|
|
|
redMessageQueue.add(event);
|
|
|
|
|
if (!isRedPlaying) {
|
|
|
|
|
isRedPlaying = true;
|
|
|
|
|
processNextRedMessage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
redMessageQueue.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processNextRedMessage() {
|
|
|
|
|
RedBean redBean;
|
|
|
|
|
synchronized (RedQueueLock) {
|
|
|
|
|
if (redMessageQueue.isEmpty()) {
|
|
|
|
|
isRedPlaying = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
redBean = redMessageQueue.remove(0);
|
|
|
|
|
}
|
|
|
|
|
showPiaoPingMessageRed(redBean);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-14 17:38:30 +08:00
|
|
|
private void showPiaoPingMessageRed(RedBean redBean) {
|
2025-10-28 19:13:52 +08:00
|
|
|
try {
|
|
|
|
|
// 清理之前的视图(如果存在)
|
|
|
|
|
if (currentRedView != null && currentRedView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentRedView.getParent();
|
|
|
|
|
parent.removeView(currentRedView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (decorView2 == null) {
|
|
|
|
|
decorView2 = (ViewGroup) getWindow().getDecorView();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentRedView = LayoutInflater.from(this).inflate(com.xscm.moduleutil.R.layout.item_piaoping_red, null);
|
|
|
|
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
|
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
layoutParams.topMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 140);
|
|
|
|
|
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
|
|
|
|
currentRedView.setLayoutParams(layoutParams);
|
|
|
|
|
decorView2.addView(currentRedView);
|
|
|
|
|
|
|
|
|
|
updateRedFloatingViewData(currentRedView, redBean);
|
|
|
|
|
// 播放红包音效
|
|
|
|
|
playRedPacketSound();
|
|
|
|
|
resetAndStartXlhAnimation(currentRedView, () -> {
|
|
|
|
|
// 清理当前视图
|
|
|
|
|
if (currentRedView != null && currentRedView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentRedView.getParent();
|
|
|
|
|
parent.removeView(currentRedView);
|
|
|
|
|
}
|
|
|
|
|
currentRedView = null;
|
|
|
|
|
|
|
|
|
|
// 处理队列中的下一条消息
|
|
|
|
|
synchronized (RedQueueLock) {
|
|
|
|
|
isRedPlaying = false;
|
|
|
|
|
processNextRedMessage();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("显示红包飘屏失败", e);
|
|
|
|
|
// 出现异常时继续处理队列
|
|
|
|
|
synchronized (RedQueueLock) {
|
|
|
|
|
isRedPlaying = false;
|
|
|
|
|
processNextRedMessage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-14 17:38:30 +08:00
|
|
|
|
2025-10-28 19:13:52 +08:00
|
|
|
// 在类中添加成员变量
|
|
|
|
|
private MediaPlayer redPacketMediaPlayer = null;
|
|
|
|
|
private boolean isRedPacketMediaPrepared = false;
|
2025-11-14 17:38:30 +08:00
|
|
|
|
2025-10-28 19:13:52 +08:00
|
|
|
// 添加播放红包音效的方法
|
|
|
|
|
private void playRedPacketSound() {
|
|
|
|
|
try {
|
|
|
|
|
if (!isRedPacketMediaPrepared) {
|
|
|
|
|
// 第一次初始化MediaPlayer
|
|
|
|
|
if (redPacketMediaPlayer == null) {
|
|
|
|
|
redPacketMediaPlayer = MediaPlayer.create(this, com.xscm.moduleutil.R.raw.red_packet_come); // 假设音效文件名为red_packet_sound.mp3
|
|
|
|
|
redPacketMediaPlayer.setOnPreparedListener(mp -> {
|
|
|
|
|
isRedPacketMediaPrepared = true;
|
|
|
|
|
mp.start();
|
|
|
|
|
});
|
|
|
|
|
redPacketMediaPlayer.setOnCompletionListener(mp -> {
|
|
|
|
|
// 播放完成后重置,以便下次重新播放
|
|
|
|
|
try {
|
|
|
|
|
mp.seekTo(0);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("MediaPlayer重置失败", e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (redPacketMediaPlayer != null) {
|
|
|
|
|
redPacketMediaPlayer.prepareAsync(); // 异步准备
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 已经准备好了,直接重新播放
|
|
|
|
|
if (redPacketMediaPlayer != null && !redPacketMediaPlayer.isPlaying()) {
|
|
|
|
|
redPacketMediaPlayer.seekTo(0);
|
|
|
|
|
redPacketMediaPlayer.start();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("播放红包音效失败", e);
|
2025-11-14 17:38:30 +08:00
|
|
|
isRedPacketMediaPrepared = false;
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-14 17:38:30 +08:00
|
|
|
private void updateRedFloatingViewData(View view, RedBean redBean) {
|
2025-10-28 19:13:52 +08:00
|
|
|
TextView textView = view.findViewById(R.id.tv_name);
|
|
|
|
|
|
|
|
|
|
if (redBean != null) {
|
|
|
|
|
String fullText = redBean.getText();
|
|
|
|
|
if (redBean.getNickname() != null && redBean.getRoom_name() != null) {
|
|
|
|
|
SpannableStringBuilder builder = new SpannableStringBuilder(fullText);
|
|
|
|
|
|
|
|
|
|
// 为用户名设置蓝色
|
|
|
|
|
int userNameStart = fullText.indexOf(redBean.getNickname());
|
|
|
|
|
if (userNameStart >= 0) {
|
|
|
|
|
builder.setSpan(
|
|
|
|
|
new ForegroundColorSpan(ContextCompat.getColor(this, com.xscm.moduleutil.R.color.colorPrimary)),
|
|
|
|
|
userNameStart,
|
|
|
|
|
userNameStart + redBean.getNickname().length(),
|
|
|
|
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 为房间名设置蓝色
|
|
|
|
|
int roomNameStart = fullText.indexOf(redBean.getRoom_name());
|
|
|
|
|
if (roomNameStart >= 0) {
|
|
|
|
|
builder.setSpan(
|
|
|
|
|
new ForegroundColorSpan(ContextCompat.getColor(this, com.xscm.moduleutil.R.color.colorPrimary)),
|
|
|
|
|
roomNameStart,
|
|
|
|
|
roomNameStart + redBean.getRoom_name().length(),
|
|
|
|
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
textView.setText(builder);
|
|
|
|
|
} else {
|
|
|
|
|
textView.setText(fullText);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
textView.setText("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
view.setOnClickListener(v -> {
|
|
|
|
|
// 点击时执行跳转操作
|
|
|
|
|
handleRedItemClick(redBean);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理下一个MQTT消息
|
|
|
|
|
private void processNextMqttMessage() {
|
|
|
|
|
MqttBean.ListBean mqttBean;
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
if (mqttMessageQueue.isEmpty()) {
|
|
|
|
|
isMqttPlaying = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mqttBean = mqttMessageQueue.remove(0);
|
|
|
|
|
}
|
|
|
|
|
showFloatingMessage(mqttBean);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理下一个XLH消息
|
|
|
|
|
private void processNextXlhMessage() {
|
|
|
|
|
XLHBean xlhBean;
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
if (xlhMessageQueue.isEmpty()) {
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
xlhBean = xlhMessageQueue.remove(0);
|
|
|
|
|
}
|
|
|
|
|
showPiaoPingMessageXlh(xlhBean);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ViewGroup decorView;//礼物的
|
|
|
|
|
ViewGroup decorView1;//巡乐会的
|
|
|
|
|
ViewGroup decorView2;//红包的
|
|
|
|
|
|
|
|
|
|
private void showFloatingMessage(MqttBean.ListBean mqttBean) {
|
|
|
|
|
|
|
|
|
|
// QXGiftDriftView.getInstance( this).addGiftModel(mqttBean);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 清理之前的视图(如果存在)
|
|
|
|
|
if (currentMqttView != null && currentMqttView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentMqttView.getParent();
|
|
|
|
|
parent.removeView(currentMqttView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (decorView == null) {
|
|
|
|
|
decorView = (ViewGroup) getWindow().getDecorView();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentMqttView = LayoutInflater.from(this).inflate(com.xscm.moduleutil.R.layout.item_piaoping, null);
|
|
|
|
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
|
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
layoutParams.topMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 70);
|
|
|
|
|
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
|
|
|
|
currentMqttView.setLayoutParams(layoutParams);
|
|
|
|
|
decorView.addView(currentMqttView);
|
|
|
|
|
|
|
|
|
|
updateFloatingViewData(currentMqttView, mqttBean);
|
|
|
|
|
resetAndStartMqttAnimation(currentMqttView, () -> {
|
|
|
|
|
// 清理当前视图
|
|
|
|
|
if (currentMqttView != null && currentMqttView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentMqttView.getParent();
|
|
|
|
|
parent.removeView(currentMqttView);
|
|
|
|
|
}
|
|
|
|
|
currentMqttView = null;
|
|
|
|
|
|
|
|
|
|
// 处理队列中的下一条消息
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
isMqttPlaying = false;
|
|
|
|
|
processNextMqttMessage();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("显示MQTT飘屏失败", e);
|
|
|
|
|
// 出现异常时继续处理队列
|
|
|
|
|
synchronized (mqttQueueLock) {
|
|
|
|
|
isMqttPlaying = false;
|
|
|
|
|
processNextMqttMessage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showPiaoPingMessageXlh(XLHBean event) {
|
|
|
|
|
try {
|
|
|
|
|
// 清理之前的视图(如果存在)
|
|
|
|
|
if (currentXlhView != null && currentXlhView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentXlhView.getParent();
|
|
|
|
|
parent.removeView(currentXlhView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (decorView1 == null) {
|
|
|
|
|
decorView1 = (ViewGroup) getWindow().getDecorView();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentXlhView = LayoutInflater.from(this).inflate(com.xscm.moduleutil.R.layout.item_piaoping_xlh, null);
|
|
|
|
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
|
|
|
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
|
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
layoutParams.topMargin = com.sunfusheng.marqueeview.DisplayUtil.dip2px(this, 100);
|
|
|
|
|
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
|
|
|
|
currentXlhView.setLayoutParams(layoutParams);
|
|
|
|
|
decorView1.addView(currentXlhView);
|
|
|
|
|
|
|
|
|
|
updateXlhFloatingViewData(currentXlhView, event);
|
|
|
|
|
resetAndStartXlhAnimation(currentXlhView, () -> {
|
|
|
|
|
// 清理当前视图
|
|
|
|
|
if (currentXlhView != null && currentXlhView.getParent() != null) {
|
|
|
|
|
ViewGroup parent = (ViewGroup) currentXlhView.getParent();
|
|
|
|
|
parent.removeView(currentXlhView);
|
|
|
|
|
}
|
|
|
|
|
currentXlhView = null;
|
|
|
|
|
|
|
|
|
|
// 处理队列中的下一条消息
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
processNextXlhMessage();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("显示XLH飘屏失败", e);
|
|
|
|
|
// 出现异常时继续处理队列
|
|
|
|
|
synchronized (xlhQueueLock) {
|
|
|
|
|
isXlhPlaying = false;
|
|
|
|
|
processNextXlhMessage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void resetAndStartMqttAnimation(View view, Runnable onAnimationEnd) {
|
|
|
|
|
try {
|
|
|
|
|
int screenWidth = getScreenWidth();
|
|
|
|
|
// 设置初始位置:在屏幕右侧外部(完全不可见)
|
|
|
|
|
view.setTranslationX(screenWidth);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TranslateAnimation enterAnim = new TranslateAnimation(
|
|
|
|
|
Animation.ABSOLUTE, screenWidth,
|
|
|
|
|
Animation.ABSOLUTE, (screenWidth - SystemUtils.getWidth(316)) / 2,
|
|
|
|
|
Animation.ABSOLUTE, 0,
|
|
|
|
|
Animation.ABSOLUTE, 0
|
|
|
|
|
);
|
|
|
|
|
enterAnim.setDuration(1500);
|
|
|
|
|
enterAnim.setInterpolator(new DecelerateInterpolator(2.0f));
|
|
|
|
|
enterAnim.setAnimationListener(new Animation.AnimationListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationStart(Animation animation) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animation animation) {
|
|
|
|
|
// 停留后退出
|
|
|
|
|
postDelayed(() -> {
|
|
|
|
|
TranslateAnimation exitAnim = new TranslateAnimation(
|
|
|
|
|
Animation.ABSOLUTE, (screenWidth - SystemUtils.getWidth(316)) / 2,
|
|
|
|
|
Animation.ABSOLUTE, -screenWidth,
|
|
|
|
|
Animation.ABSOLUTE, 0,
|
|
|
|
|
Animation.ABSOLUTE, 0
|
|
|
|
|
);
|
|
|
|
|
exitAnim.setDuration(3000);
|
|
|
|
|
exitAnim.setInterpolator(new DecelerateInterpolator(2f));
|
|
|
|
|
exitAnim.setAnimationListener(new Animation.AnimationListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationStart(Animation animation) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animation animation) {
|
|
|
|
|
// 移除视图并处理下一个
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationRepeat(Animation animation) {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
view.startAnimation(exitAnim);
|
|
|
|
|
}, 5000); // 停留1秒
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationRepeat(Animation animation) {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
view.startAnimation(enterAnim);
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("MQTT动画启动失败", e);
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加获取屏幕宽度的方法
|
|
|
|
|
private int getScreenWidth() {
|
|
|
|
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
|
|
|
|
if (getWindowManager() != null) {
|
|
|
|
|
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
|
|
|
|
return displayMetrics.widthPixels;
|
|
|
|
|
}
|
|
|
|
|
return getResources().getDisplayMetrics().widthPixels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void resetAndStartXlhAnimation(View view, Runnable onAnimationEnd) {
|
|
|
|
|
try {
|
|
|
|
|
view.setTranslationX(view.getWidth());
|
|
|
|
|
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", view.getWidth(), 0f);
|
|
|
|
|
animator1.setDuration(1500);
|
|
|
|
|
animator1.setInterpolator(new DecelerateInterpolator(2.0f));
|
|
|
|
|
animator1.start();
|
|
|
|
|
|
|
|
|
|
view.postDelayed(() -> {
|
|
|
|
|
try {
|
|
|
|
|
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "translationX", 0f, -view.getWidth());
|
|
|
|
|
animator2.setDuration(1500);
|
|
|
|
|
animator2.setInterpolator(new DecelerateInterpolator(2.0f));
|
|
|
|
|
animator2.addListener(new AnimatorListenerAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationCancel(Animator animation) {
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
animator2.start();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("XLH动画执行失败", e);
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
}, 5000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogUtils.e("XLH动画启动失败", e);
|
|
|
|
|
onAnimationEnd.run();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateFloatingViewData(View view, MqttBean.ListBean mqttBean) {
|
|
|
|
|
TextView textView = view.findViewById(com.xscm.moduleutil.R.id.tv_name);
|
|
|
|
|
TextView textView2 = view.findViewById(com.xscm.moduleutil.R.id.tv_to_name);
|
|
|
|
|
TextView tv_time = view.findViewById(com.xscm.moduleutil.R.id.tv_num);
|
|
|
|
|
|
|
|
|
|
if (mqttBean != null) {
|
|
|
|
|
textView2.setText("送给" + (mqttBean.getToUserName() != null ? mqttBean.getToUserName() : ""));
|
|
|
|
|
textView.setText(mqttBean.getFromUserName() != null ? mqttBean.getFromUserName() : "");
|
|
|
|
|
if (mqttBean.getGift_picture() != null) {
|
|
|
|
|
ImageUtils.loadHeadCC(mqttBean.getGift_picture(), view.findViewById(com.xscm.moduleutil.R.id.iv_piaoping));
|
|
|
|
|
}
|
|
|
|
|
tv_time.setText("x" + (mqttBean.getNumber() != null ? mqttBean.getNumber() : "1"));
|
|
|
|
|
} else {
|
|
|
|
|
textView2.setText("送给");
|
|
|
|
|
textView.setText("");
|
|
|
|
|
tv_time.setText("x1");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateXlhFloatingViewData(View view, XLHBean xlhBean) {
|
|
|
|
|
TextView textView = view.findViewById(R.id.tv_name);
|
|
|
|
|
ImageView xlh_image = view.findViewById(R.id.im_xlh);
|
|
|
|
|
|
|
|
|
|
if (xlhBean != null) {
|
|
|
|
|
xlh_image.setImageDrawable(xlhBean.getFrom_type() == 1 ?
|
|
|
|
|
getResources().getDrawable(com.xscm.moduleutil.R.mipmap.xlh_jjks) :
|
|
|
|
|
getResources().getDrawable(com.xscm.moduleutil.R.mipmap.xlh_zsks));
|
|
|
|
|
textView.setText(xlhBean.getText());
|
|
|
|
|
} else {
|
|
|
|
|
textView.setText("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
view.setOnClickListener(v -> {
|
|
|
|
|
// 点击时执行跳转操作
|
|
|
|
|
handleItemClick(xlhBean);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void handleItemClick(XLHBean xlhBean) {
|
|
|
|
|
// 这里可以根据实际需求实现跳转逻辑
|
|
|
|
|
// 例如:跳转到礼物详情页面、用户主页等
|
|
|
|
|
// 使用缓存数据进入房间
|
2025-12-04 20:56:30 +08:00
|
|
|
if (ActivityUtils.getTopActivity() instanceof RoomActivity){
|
|
|
|
|
if (!Objects.equals(((RoomActivity) ActivityUtils.getTopActivity()).getRoomId(), xlhBean.getRoom_id())) {
|
|
|
|
|
((RoomActivity) ActivityUtils.getTopActivity()).refreshRoomInfo(xlhBean.getRoom_id());
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-11-14 17:38:30 +08:00
|
|
|
RoomManager.getInstance().fetchRoomDataAndEnter(getApplicationContext(), xlhBean.getRoom_id(), "", null);
|
2025-10-28 19:13:52 +08:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void handleRedItemClick(RedBean redBean) {
|
|
|
|
|
// 这里可以根据实际需求实现跳转逻辑
|
|
|
|
|
// 例如:跳转到礼物详情页面、用户主页等
|
|
|
|
|
// 使用缓存数据进入房间
|
2025-12-04 20:56:30 +08:00
|
|
|
if (ActivityUtils.getTopActivity() instanceof RoomActivity){
|
|
|
|
|
if (!Objects.equals(((RoomActivity) ActivityUtils.getTopActivity()).getRoomId(), redBean.getRoom_id())) {
|
|
|
|
|
((RoomActivity) ActivityUtils.getTopActivity()).refreshRoomInfo(redBean.getRoom_id());
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-11-14 17:38:30 +08:00
|
|
|
RoomManager.getInstance().fetchRoomDataAndEnter(getApplicationContext(), redBean.getRoom_id(), "", null);
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-12-03 20:02:14 +08:00
|
|
|
// @Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
|
|
// public void onEvent(ChatInfo event) {
|
|
|
|
|
// if(ActivityUtils.getTopActivity() instanceof WebViewActivity){
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
// String id = event.getId().replace("g", "");
|
|
|
|
|
// Intent intent = new Intent(this, WebViewActivity.class);
|
|
|
|
|
// intent.putExtra("url", String.format(WebUrlConstants.INSTANCE.getWEB_SET_GROUP_URL(), SpUtil.getToken(), id));
|
|
|
|
|
// startActivity(intent);
|
|
|
|
|
// }
|
2025-10-28 19:13:52 +08:00
|
|
|
|
|
|
|
|
|
2025-11-14 17:38:30 +08:00
|
|
|
public void singleTaskToActivity(Class<?> clazz) {
|
2025-10-28 19:13:52 +08:00
|
|
|
Intent intent = new Intent(this, clazz);
|
2025-10-30 09:19:46 +08:00
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
2025-11-14 17:38:30 +08:00
|
|
|
startActivity(intent);
|
2025-10-28 19:13:52 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-14 17:38:30 +08:00
|
|
|
public void toActivity(Class<?> clazz, Bundle bundle) {
|
2025-10-28 19:13:52 +08:00
|
|
|
Intent intent = new Intent(this, clazz);
|
|
|
|
|
intent.putExtras(bundle);
|
|
|
|
|
startActivity(intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|