From 748912d3d18191d4e00baabea9df36bfd33cffe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=B0=8F=E6=B1=9F?= <461355754@qq.com> Date: Fri, 12 Sep 2025 09:08:14 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BF=AE=E6=94=B9=E6=92=AD=E6=94=BE=E7=A4=BC?= =?UTF-8?q?=E7=89=A9=E7=89=B9=E6=95=88=E4=BB=A3=E7=A0=81=202=EF=BC=9A?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=8E=E6=88=BF=E9=97=B4=E8=BF=9B=E5=85=A5?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E9=A1=B5=E9=9D=A2=E5=87=BA=E7=8E=B0=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E5=9B=9E=E5=88=B0=E6=88=BF=E9=97=B4=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- gradle.properties | 2 +- .../moduleutil/base/CommonAppContext.java | 17 + .../com/xscm/moduleutil/bean/GiftBean.java | 1 + .../moduleutil/bean/room/EMMessageInfo.java | 2 +- .../dialog/giftLottery/GiftLotteryDialog.java | 28 +- .../moduleutil/widget/AvatarFrameView.java | 219 ++++--- .../xscm/moduleutil/widget/BaseWheatView.java | 16 +- .../src/main/res/layout/dialog_city_time.xml | 4 +- .../src/main/res/layout/dialog_mirroe_sky.xml | 4 +- .../main/res/layout/dialog_pinnacle_time.xml | 4 +- modulemain/src/main/AndroidManifest.xml | 2 +- .../modulemain/activity/MainActivity.java | 29 +- moduleroom/src/main/AndroidManifest.xml | 7 +- .../moduleroom/activity/RoomActivity.java | 490 ++++++++++++---- .../PublicScreenEaseChatFragment.java | 548 +++++++++++++----- .../fragment/RoomCabinFragment.java | 2 +- .../modulevocal/activity/RevenueActivity.java | 34 ++ .../modulevocal/fragment/RevenueFragment.java | 10 +- 19 files changed, 1056 insertions(+), 367 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 84844cd..a80d20a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,7 +55,7 @@ android { } buildTypes { release { - minifyEnabled true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release @@ -77,7 +77,7 @@ android { debug { debuggable true - minifyEnabled true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.debug diff --git a/gradle.properties b/gradle.properties index 57c9693..8f6a48a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,7 +30,7 @@ isBuildModule=false android.injected.testOnly=false APP_VERSION_NAME=1.0.0 -APP_VERSION_CODE=120 +APP_VERSION_CODE=121 org.gradle.jvm.toolchain.useLegacyAdapters=false #org.gradle.java.home=C\:\\Users\\qx\\.jdks\\ms-17.0.15 diff --git a/moduleUtil/src/main/java/com/xscm/moduleutil/base/CommonAppContext.java b/moduleUtil/src/main/java/com/xscm/moduleutil/base/CommonAppContext.java index 94cdece..fd4b189 100644 --- a/moduleUtil/src/main/java/com/xscm/moduleutil/base/CommonAppContext.java +++ b/moduleUtil/src/main/java/com/xscm/moduleutil/base/CommonAppContext.java @@ -91,6 +91,23 @@ public class CommonAppContext extends MultiDexApplication { private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); private ScheduledExecutorService scheduledExecutorServiceRoom = null; private MqttConnect mqttConnect=null; + + // 添加后台状态标记 + private boolean wasInBackground = false; + + public void onAppBackground() { + wasInBackground = true; + } + + public void onAppForeground() { + wasInBackground = false; + } + + public boolean wasInBackground() { + return wasInBackground; + } + + @Override public void onCreate() { super.onCreate(); diff --git a/moduleUtil/src/main/java/com/xscm/moduleutil/bean/GiftBean.java b/moduleUtil/src/main/java/com/xscm/moduleutil/bean/GiftBean.java index 50503b6..471fcbd 100644 --- a/moduleUtil/src/main/java/com/xscm/moduleutil/bean/GiftBean.java +++ b/moduleUtil/src/main/java/com/xscm/moduleutil/bean/GiftBean.java @@ -24,4 +24,5 @@ public class GiftBean { private int count; private String user_id; private int num; + private boolean is_paly =false; } diff --git a/moduleUtil/src/main/java/com/xscm/moduleutil/bean/room/EMMessageInfo.java b/moduleUtil/src/main/java/com/xscm/moduleutil/bean/room/EMMessageInfo.java index 4839ee9..8e4b252 100644 --- a/moduleUtil/src/main/java/com/xscm/moduleutil/bean/room/EMMessageInfo.java +++ b/moduleUtil/src/main/java/com/xscm/moduleutil/bean/room/EMMessageInfo.java @@ -158,11 +158,11 @@ public class EMMessageInfo implements MultiItemEntity { case QXRoomMessageTypeRoomDress: case QXRoomMessageTypeRoomOnline: case QXRoomMessageTypeRoomOPK: - case QXRoomMessageTypeRoomOMh: case QXRoomMessageTypeRoomFriendPartDidChanged: case QXRoomMessageTypeSeatDidChanged: case QXRoomMessageTypehm: return 1; + case QXRoomMessageTypeRoomOMh: case QXRoomMessageTypeGift: return 3; case 1: diff --git a/moduleUtil/src/main/java/com/xscm/moduleutil/dialog/giftLottery/GiftLotteryDialog.java b/moduleUtil/src/main/java/com/xscm/moduleutil/dialog/giftLottery/GiftLotteryDialog.java index 1cadc32..2e67724 100644 --- a/moduleUtil/src/main/java/com/xscm/moduleutil/dialog/giftLottery/GiftLotteryDialog.java +++ b/moduleUtil/src/main/java/com/xscm/moduleutil/dialog/giftLottery/GiftLotteryDialog.java @@ -322,7 +322,7 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment 0 && box_price > 0) { if (type == 10) { updateBackground(mBinding.mirroeSky.llOne, icon > box_price, drawableX, drawableW); - updateBackground(mBinding.mirroeSky.llTen, icon > box_price * 10, drawableX, drawableW); - updateBackground(mBinding.mirroeSky.llHundred, icon > box_price * 100, drawableX, drawableW); + updateBackground(mBinding.mirroeSky.llTen, icon > box_price * 6, drawableX, drawableW); + updateBackground(mBinding.mirroeSky.llHundred, icon > box_price * 9, drawableX, drawableW); } else if (type == 11) { updateBackground(mBinding.cityTime.llOne, icon > box_price, drawableX, drawableW); - updateBackground(mBinding.cityTime.llTen, icon > box_price * 10, drawableX, drawableW); - updateBackground(mBinding.cityTime.llHundred, icon > box_price * 100, drawableX, drawableW); + updateBackground(mBinding.cityTime.llTen, icon > box_price * 6, drawableX, drawableW); + updateBackground(mBinding.cityTime.llHundred, icon > box_price * 9, drawableX, drawableW); } else if (type == 12) { updateBackground(mBinding.pinnacleTime.llOne, icon > box_price, drawableX, drawableW); - updateBackground(mBinding.pinnacleTime.llTen, icon > box_price * 10, drawableX, drawableW); - updateBackground(mBinding.pinnacleTime.llHundred, icon > box_price * 100, drawableX, drawableW); + updateBackground(mBinding.pinnacleTime.llTen, icon > box_price * 6, drawableX, drawableW); + updateBackground(mBinding.pinnacleTime.llHundred, icon > box_price * 9, drawableX, drawableW); } else { // 兜底处理:未知 type 时全部设为不可点击 + 默认背景 setAllBackgroundToDefault(drawableW); @@ -725,17 +725,17 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment { -// if (!isDestroyed) { - handleVideoComplete(); -// } - }); - } +// EventBus.getDefault().post(new GiftAvatarBean()); + LogUtils.e("@@@@" + "EventBus onVideoComplete"); +// if (Looper.myLooper() == Looper.getMainLooper()) { +// handleVideoComplete(); +// } else { +// mainHandler.post(() -> { +//// if (!isDestroyed) { +// handleVideoComplete(); +//// } +// }); +// } } private void handleVideoComplete() { @@ -209,6 +215,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { super(context, attrs, defStyleAttr); mBinding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.room_view_svga_anim, this, true); initViews(); + } private void initViews() { @@ -231,9 +238,49 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { // 初始化播放管理器 playbackManager = new PlaybackManager(mainHandler); - if (mBinding != null) { - mBinding.playView.setAnimListener(this); - } + // 获取 MP4PlaybackCallback 单例实例并设置引用 + MP4PlaybackCallback callback = MP4PlaybackCallback.getInstance(); + callback.setAvatarFrameView(this); + // 设置播放完成监听 + mBinding.playView.setAnimListener(callback); + +// if (mBinding != null) { +// mBinding.playView.setAnimListener(this); +// } + +// MP4PlaybackCallback = new IAnimListener() { +// @Override +// public boolean onVideoConfigReady(@NonNull AnimConfig animConfig) { +// return false; +// } +// +// @Override +// public void onVideoStart() { +// +// } +// +// @Override +// public void onVideoRender(int i, @Nullable AnimConfig animConfig) { +// +// } +// +// @Override +// public void onVideoComplete() { +// onPlaybackComplete(); +// } +// +// @Override +// public void onVideoDestroy() { +// +// } +// +// @Override +// public void onFailed(int i, @Nullable String s) { +// onPlaybackComplete(); +// } +// }; +// // 设置播放完成监听 +// mBinding.playView.setAnimListener(MP4PlaybackCallback); } private String getFileExtension(String url) { @@ -264,11 +311,6 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { return; } - // 关键:即使 isPlaying 为 true,也要检查实际播放状态 -// if (isPlaying && isActuallyPlaying()) { -// Logger.d("AvatarFrameView", "Already playing, skip"); -// return; -// } PlayItem item = playQueue.poll(); if (item != null) { // 通知开始播放 @@ -278,42 +320,12 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { // 处理播放项目 processPlayItem(item); -// isPlaying = true; -// Logger.d("AvatarFrameView", "Playing item, remaining queue size: " + playQueue.size()); -// RenderType type = null; -// String ext = getFileExtension(item.url); -// if ("svga".equalsIgnoreCase(ext)) { -// type = RenderType.SVGA; -// } else if ("mp4".equalsIgnoreCase(ext)) { -// type = RenderType.MP4; -// } -// -// if (type == null) { -// isPlaying = false; -// playNextFromQueue(); // 跳过无效项 -// return; -// } -// -// clearPrevious(); -// renderType = type; -// mType = item.type; -// -// switch (type) { -// case SVGA: -// mBinding.playView.stopPlay(); -// mBinding.playView.setVisibility(View.GONE); -// loadSVGA(item.url); -// break; -// case MP4: -// mBinding.playView.setVisibility(View.VISIBLE); -// downloadAndPlayMp4(item.url); -// break; -// } } else { isPlaying = false; Logger.d("AvatarFrameView", "Queue is empty, stop playing"); } } + // 添加统一的播放完成处理方法 private void onPlaybackComplete() { mainHandler.post(() -> { @@ -329,7 +341,6 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { if (playQueue.size() % 5 == 0) { performLightMemoryCleanup(); } - // 继续处理队列中的下一个项目 playNextFromQueue(); }); @@ -400,10 +411,10 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { playQueue.add(new PlayItem(url, type2)); Logger.d("AvatarFrameView", "Added to queue, queue size: " + playQueue.size() + ", url: " + url); - if (type2==3){ + if (type2 == 3) { // playNextFromQueue(); loadSVGA(url); - }else { + } else { // 如果当前没有在播放,则开始播放 if (!isPlaying || !isActuallyPlaying()) { @@ -492,14 +503,17 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { boolean isTxk = false; - private void downloadAndPlayMp4(String url) { + public void downloadAndPlayMp4(String url) { // 提取文件名 String fileName = url.substring(url.lastIndexOf("/")); String filePath = getContext().getCacheDir().getAbsolutePath() + fileName; + + LogUtils.e("@@@@@filePath: " + filePath.toString()); File file = new File(filePath); if (!file.exists()) { + LogUtils.e("无缓存"); // 使用OkHttp进行下载 OkHttpClient client = new OkHttpClient(); @@ -514,25 +528,43 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { onPlaybackComplete(); } + // 更简单的优化版本 @Override public void onResponse(Call call, Response response) throws IOException { + LogUtils.d("@@@@", "onResponse" + Thread.currentThread().getName()); if (response.isSuccessful()) { - // 保存文件到缓存目录 try (ResponseBody responseBody = response.body()) { if (responseBody != null) { + // 在后台线程处理文件保存 + + String fileName = url.substring(url.lastIndexOf("/")); + String filePath = getContext().getCacheDir().getAbsolutePath() + fileName; File downloadedFile = new File(filePath); - FileOutputStream fos = new FileOutputStream(downloadedFile); - fos.write(responseBody.bytes()); - fos.close(); - isTxk = true; - // 在主线程中播放动画 - mainHandler.post(() -> { - playMp4File(downloadedFile); -// if (isTxk) { -// mBinding.playView.setLoop(1); -// } - mBinding.playView.startPlay(downloadedFile); - }); + + // 使用流式传输避免大文件卡顿 + try (InputStream inputStream = responseBody.byteStream(); + FileOutputStream fos = new FileOutputStream(downloadedFile)) { + + // 定义缓冲区大小(8KB) + byte[] buffer = new byte[1024 * 1024]; + int bytesRead; + + // 流式读取并写入文件 + while ((bytesRead = inputStream.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); + } + + fos.flush(); + isTxk = true; + mainHandler.post(() -> { + LogUtils.d("@@@@Thread", Thread.currentThread().getName()); + playMp4File(file); + }); + } catch (IOException e) { + LogUtils.e("MP4文件保存失败: " + e.getMessage()); + } + + } else { mainHandler.post(() -> onPlaybackComplete()); } @@ -540,7 +572,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { LogUtils.e("MP4文件保存失败: " + e.getMessage()); mainHandler.post(() -> onPlaybackComplete()); } - }else { + } else { LogUtils.e("MP4下载响应失败"); mainHandler.post(() -> onPlaybackComplete()); } @@ -561,9 +593,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { private void playMp4File(File file) { try { if (mBinding != null && file != null && file.exists()) { - // 设置播放完成监听 - mBinding.playView.setAnimListener(new MP4PlaybackCallback()); - +// mBinding.playView.setAnimListener(new MP4PlaybackCallback()); // 设置循环次数(根据mType决定) if (mType == 1) { mBinding.playView.setLoop(0); // 无限循环 @@ -766,7 +796,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { } }); // 设置循环次数 - if (mType == 1|| mType == 3) { + if (mType == 1 || mType == 3) { svgaSurface.setLoops(0); // 无限循环 } else { svgaSurface.setLoops(1); // 播放一次 @@ -819,7 +849,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { } }); // 设置循环次数 - if (mType == 1|| mType == 3) { + if (mType == 1 || mType == 3) { svgaSurface.setLoops(0); // 无限循环 } else { svgaSurface.setLoops(1); // 播放一次 @@ -1233,6 +1263,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { // 清理当前正在播放的内容 clearPrevious(); } + // 在类成员变量中添加 private static final int PLAYBACK_TIMEOUT = 10000; // 10秒超时 private Map playbackStartTimeMap = new HashMap<>(); @@ -1375,12 +1406,40 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { } // 在 AvatarFrameView 类中添加以下代码 - // MP4播放完成监听器 - private class MP4PlaybackCallback implements IAnimListener { +// private IAnimListener MP4PlaybackCallback; + // 在 AvatarFrameView 类的成员变量区域添加单例实例 + private static volatile MP4PlaybackCallback sInstance; + + private static class MP4PlaybackCallback implements IAnimListener { + private AvatarFrameView avatarFrameView; + + private MP4PlaybackCallback() { + // 私有构造函数 + } + + // 获取单例实例的方法 + public static MP4PlaybackCallback getInstance() { + if (sInstance == null) { + synchronized (MP4PlaybackCallback.class) { + if (sInstance == null) { + sInstance = new MP4PlaybackCallback(); + } + } + } + return sInstance; + } + + // 设置外部引用的方法 + public void setAvatarFrameView(AvatarFrameView view) { + this.avatarFrameView = view; + } + @Override public void onFailed(int i, @Nullable String s) { - LogUtils.e(TAG, "MP4 playback failed: " + s); - onPlaybackComplete(); + LogUtils.e(AvatarFrameView.TAG, "MP4 playback failed: " + s); + if (avatarFrameView != null) { + avatarFrameView.onPlaybackComplete(); + } } @Override @@ -1400,7 +1459,9 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener { @Override public void onVideoComplete() { - onPlaybackComplete(); + if (avatarFrameView != null) { + avatarFrameView.onPlaybackComplete(); + } } @Override diff --git a/moduleUtil/src/main/java/com/xscm/moduleutil/widget/BaseWheatView.java b/moduleUtil/src/main/java/com/xscm/moduleutil/widget/BaseWheatView.java index a2e991c..60fc4a1 100644 --- a/moduleUtil/src/main/java/com/xscm/moduleutil/widget/BaseWheatView.java +++ b/moduleUtil/src/main/java/com/xscm/moduleutil/widget/BaseWheatView.java @@ -15,6 +15,7 @@ import com.opensource.svgaplayer.SVGAImageView; import com.xscm.moduleutil.R; import com.xscm.moduleutil.base.RoomRollModel; import com.xscm.moduleutil.bean.FaceBean; +import com.xscm.moduleutil.bean.RoomMessageEvent; import com.xscm.moduleutil.bean.UserOnlineStatusBean; import com.xscm.moduleutil.bean.room.ClosePhone; import com.xscm.moduleutil.bean.room.RoomClearCardiacAllModel; @@ -272,7 +273,7 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe public void userJoined(int userId, int elapsd) { if (pitBean != null && pitBean.getUser_id() != null && !pitBean.getUser_id().equals("0")) { if (pitBean.getUser_id().equals(userId + "")) { - iv_on_line.setVisibility(GONE); +// iv_on_line.setVisibility(GONE); } } } @@ -295,6 +296,19 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe } + @Subscribe(threadMode = ThreadMode.MAIN) + public void subscribeMessages(RoomMessageEvent roomMessageEvent) { + if(roomMessageEvent.getMsgType()==1058){ + if (roomMessageEvent.getText().getUser_id().equals(pitBean.getUser_id())){ + if (roomMessageEvent.getText().getType()==1){ + iv_on_line.setVisibility(GONE); + }else { + iv_on_line.setVisibility(VISIBLE); + } + } + } + } + /** * 开始倒计时 diff --git a/moduleUtil/src/main/res/layout/dialog_city_time.xml b/moduleUtil/src/main/res/layout/dialog_city_time.xml index f785109..725aa5b 100644 --- a/moduleUtil/src/main/res/layout/dialog_city_time.xml +++ b/moduleUtil/src/main/res/layout/dialog_city_time.xml @@ -65,7 +65,7 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_3" android:gravity="center" - android:text="抽十次" + android:text="抽六次" android:textSize="@dimen/sp_12" /> diff --git a/modulemain/src/main/java/com/xscm/modulemain/activity/MainActivity.java b/modulemain/src/main/java/com/xscm/modulemain/activity/MainActivity.java index 1d768be..9593939 100644 --- a/modulemain/src/main/java/com/xscm/modulemain/activity/MainActivity.java +++ b/modulemain/src/main/java/com/xscm/modulemain/activity/MainActivity.java @@ -363,12 +363,35 @@ public class MainActivity extends BaseMvpActivity { diff --git a/moduleroom/src/main/AndroidManifest.xml b/moduleroom/src/main/AndroidManifest.xml index e4cb6f8..6939b42 100644 --- a/moduleroom/src/main/AndroidManifest.xml +++ b/moduleroom/src/main/AndroidManifest.xml @@ -14,13 +14,14 @@ + android:screenOrientation="portrait" + android:exported="true" + /> activeDialogs = new ArrayList<>(); private List activeDialogFragments = new ArrayList<>(); + private boolean isMinimized = false; + private static final String PREF_MINIMIZED_ROOM = "minimized_room_id"; + private static final String PREF_MINIMIZED_TIME = "minimized_time"; + // 添加弹框到管理列表 public void addActiveDialog(DialogInterface dialog) { activeDialogs.add(dialog); @@ -249,44 +262,115 @@ public class RoomActivity extends BaseMvpActivity= viewX && x <= viewX + viewWidth && -// y >= viewY && y <= viewY + viewHeight) { -// // 将事件传递给该视图 -// return negativeMarginView.dispatchTouchEvent(ev); +// SharedPreferences prefs = getSharedPreferences("room_minimize_state", Context.MODE_PRIVATE); +// boolean isMinimized = prefs.getBoolean("is_minimized", false); +// +// if (isMinimized) { +// // 恢复到最小化的房间 +// String minimizedRoomId = prefs.getString(PREF_MINIMIZED_ROOM, null); +// if (minimizedRoomId != null && minimizedRoomId.equals(roomId)) { +// // 当前就是最小化的房间,直接恢复 +// resumeRoomFromMinimize(); +// return; // } // } // } -// -// return super.dispatchTouchEvent(ev); -// } + + // 其他情况按正常流程处理 + String newRoomId = intent.getStringExtra("roomId"); + String newPassword = intent.getStringExtra("password"); + + if (!TextUtils.isEmpty(newRoomId) && !newRoomId.equals(roomId)) { +// switchToRoom(newRoomId, newPassword); + releaseRoom(); + startActivity(intent); + finish(); + } + } + + private void resumeRoomFromMinimize() { + // 从最小化状态恢复房间 + isMinimized = false; + clearMinimizeState(); + + // 恢复房间状态 + resumeRoomState(); + + // 确保UI正确显示 + if (mBinding != null) { + // 恢复UI状态 + } + } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + // 拦截返回键,显示退出对话框而不是直接退出 + showExitRoomDialog(); + return true; + } +// else if (keyCode == KeyEvent.KEYCODE_HOME) { +// // Home 键按下时,保存状态但不特殊处理 +// // 系统会自动将应用最小化 +//// saveMinimizeState(); +// return super.onKeyDown(keyCode, event); +// } + return false; + } + + private void showExitRoomDialog() { + ExitRoomBottomSheet bottomSheet = ExitRoomBottomSheet.newInstance(); + bottomSheet.setOnOptionSelectedListener(new ExitRoomBottomSheet.OnOptionSelectedListener() { + @Override + public void onMinimize() { + // 处理最小化逻辑,比如不销毁 Activity,仅移至后台 +// CommonAppContext.getInstance().isShow = false; +// ARouter.getInstance().build(ARouteConstants.ME).navigation();//栈顶复用 +// moveTaskToBack(true); + + CommonAppContext.getInstance().isShow = false; + ARouter.getInstance().build(ARouteConstants.ME) + .withFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .navigation(); +// moveTaskToBack(true); + + // 处理最小化逻辑 + minimizeToBackground(); + } + + @Override + public void onExitRoom() { + // 调用退出房间方法 + MvpPre.quitRoom(roomId, SpUtil.getUserId() + ""); + + // 真正退出房间 + performExitRoom(); + } + + @Override + public void onCancel() { + // 用户点击取消,不做任何事 + } + }); + bottomSheet.show(getSupportFragmentManager(), "ExitRoomBottomSheet"); + addActiveDialogFragment(bottomSheet); + } @Override public void onConfigurationChanged(@NonNull Configuration newConfig) { @@ -371,6 +455,9 @@ public class RoomActivity extends BaseMvpActivity EventBus.getDefault().post(new ShowOnWheatDialogEvent()), // 10000); + isSave = false; + sDestroied = false; + isMinimized = false; overridePendingTransition(0, 0); // 关闭转场动画 @@ -380,8 +467,11 @@ public class RoomActivity extends BaseMvpActivity 30 * 60 * 1000) { + // 清理过期的最小化状态 + clearMinimizeState(); + } + } + } /** * 在子线程中执行网络请求,避免阻塞主线程 */ @@ -989,7 +1094,7 @@ public class RoomActivity extends BaseMvpActivity playQueue = new ArrayList(); private void handleMsgType1005(RoomMessageEvent messageEvent, RoomMessageEvent.T text) { if (text == null || mRoomInfoResp == null || mRoomInfoResp.getRoom_info() == null) return; @@ -998,32 +1103,42 @@ public class RoomActivity extends BaseMvpActivity() { - @Override - public Void doInBackground() throws Throwable { - // 预处理礼物数据(如果需要) - return null; - } - - @Override - public void onSuccess(Void result) { - // 在主线程中更新UI - runOnUiThread(() -> { - try { - // 使用post方法确保在下一个消息循环中执行 - mBinding.svgaGift.post(() -> { - mBinding.svgaGift.setSource(giftInfo.getPlay_image(), 2); - }); - } catch (Exception e) { - LogUtils.e("Error setting gift source: " + e.getMessage()); - } - }); - } - }); +// ThreadUtils.executeBySingle(new ThreadUtils.SimpleTask() { +// @Override +// public Void doInBackground() throws Throwable { +// // 预处理礼物数据(如果需要) +// LogUtils.d("@@@@doInBackground",Thread.currentThread().getName()); +// if ("mp4".equals(mBinding.svgaGift.getFileExtension(giftInfo.getPlay_image()))) { +// mBinding.svgaGift.downloadAndPlayMp4(giftInfo.getPlay_image()); +// } +// return null; +// } +// +// @Override +// public void onSuccess(Void result) { +// LogUtils.d("@@@@",Thread.currentThread().getName()); +// +// // 在主线程中更新UI +//// runOnUiThread(() -> { +//// try { +//// // 使用post方法确保在下一个消息循环中执行 +//// mBinding.svgaGift.post(() -> { +//// mBinding.svgaGift.setSource(giftInfo.getPlay_image(), 2); +//// }); +//// } catch (Exception e) { +//// LogUtils.e("Error setting gift source: " + e.getMessage()); +//// } +//// }); +// } +// }); List pitList = mRoomInfoResp.getRoom_info().getPit_list(); if (pitList == null) return; @@ -1056,6 +1171,21 @@ public class RoomActivity extends BaseMvpActivity appProcesses = activityManager.getRunningAppProcesses(); + if (appProcesses == null) { + return false; + } + + final String packageName = getPackageName(); + for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { + if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND + && appProcess.processName.equals(packageName)) { + return true; + } + } + return false; + } + + + private void navigateToMainPage() { + ARouter.getInstance() + .build(ARouteConstants.ME) + .withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK) + .navigation(); + + // 添加转场动画 + overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); + } + + + private void minimizeToBackground() { + isMinimized = true; + + // 保存最小化状态和房间ID + saveMinimizeState(); + + // 设置应用状态 + CommonAppContext.getInstance().isShow = false; + + // 使用 moveTaskToBack 将应用最小化 +// moveTaskToBack(true); + } + + private void saveMinimizeState() { + SharedPreferences prefs = getSharedPreferences("room_minimize_state", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(PREF_MINIMIZED_ROOM, roomId); + editor.putLong(PREF_MINIMIZED_TIME, System.currentTimeMillis()); + editor.putBoolean("is_minimized", true); + editor.apply(); + } + + private void clearMinimizeState() { + SharedPreferences prefs = getSharedPreferences("room_minimize_state", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.remove(PREF_MINIMIZED_ROOM); + editor.remove(PREF_MINIMIZED_TIME); + editor.putBoolean("is_minimized", false); + editor.apply(); + } + + private boolean wasMinimized() { + SharedPreferences prefs = getSharedPreferences("room_minimize_state", Context.MODE_PRIVATE); + return prefs.getBoolean("is_minimized", false); + } + private void queren() { // 创建并显示确认对话框 ConfirmDialog dialog = new ConfirmDialog(this, @@ -2635,25 +2864,65 @@ public class RoomActivity extends BaseMvpActivity messageQueue = new ArrayList<>(); + + @Override + public void handleMessage(@NonNull Message msg) { + if (msg.what == MSG_HANDLE_ROOM_MESSAGE) { + if (!messageQueue.isEmpty()) { + // 批量处理消息 + processBatchMessages(messageQueue); + messageQueue.clear(); + } else if (msg.obj instanceof RoomMessageEvent) { + // 处理单条消息 + processRoomMessage((RoomMessageEvent) msg.obj); + } + } + } + }; + + private void processBatchMessages(List messages) { + if (messages.isEmpty() || easeChatAdapter == null) return; + + List messageInfos = new ArrayList<>(); + for (RoomMessageEvent message : messages) { + EMMessageInfo info = createMessageInfoIfNeeded(message); + if (info != null) { + messageInfos.add(info); + } + // 发送事件总线消息 + EventBus.getDefault().post(message); + } + + if (!messageInfos.isEmpty()) { + easeChatAdapter.addData(messageInfos); + scrollToBottomIfNeed(); + } + } + + private void processRoomMessage(RoomMessageEvent message) { + if (message == null) return; + + int msgType = message.getMsgType(); + RoomMessageEvent.T text = message.getText(); + + switch (msgType) { + case 1001: + if (text != null) { + RoomJoinMountModel roomJoinMountModel = new RoomJoinMountModel( + message.getRoomId(), text.getJia_jia(), 2); + EventBus.getDefault().post(roomJoinMountModel); + } + postAndAddMessage(message); + break; + + case 1002: + postAndAddMessage(message); + break; + + case 123: + easeChatAdapter.clearData(); + postAndAddMessage(message); + break; + + case 1012: + case 1014: + case 1013: + case 1026: + case 1015: + case 1021: + case 1034: + case 1035: + case 1050: + case 1054: + case 1051: + case 1052: + case 1053: + case 1055: + case 1056: + case 1057: + case 1059: + case 1025: + case 1058: + EventBus.getDefault().post(message); + break; + + case 124: + if (text != null && text.getText() != null) { + try { + RoomMessageEvent.text parsedText = GsonUtils.fromJson( + text.getText(), RoomMessageEvent.text.class); + if (parsedText != null) { + MusicPlayBean musicPlayBean = new MusicPlayBean(); + musicPlayBean.setPosition(parsedText.getPosition()); + EventBus.getDefault().post(musicPlayBean); + } + } catch (Exception e) { + LogUtils.e("解析音乐播放消息失败", e); + } + } + break; + + case 1007: + case 1018: + case 1006: + case 1017: + case 1016: + if (text != null && text.getFromUserInfo() != null && + text.getFromUserInfo().getUser_id() == SpUtil.getUserId()) { + EMMessageInfo info = new EMMessageInfo(message); + easeChatAdapter.addData(info); + scrollToBottomIfNeed(); + } + EventBus.getDefault().post(message); + break; + + case 1003: + case 1004: + case 1000: + case 1: + case 1030: + case 1033: + case 1032: + case 1039: + postAndAddMessage(message); + break; + + case 1038: + addSingleMessage(message); + break; + + case 1049: + if (text != null && text.getStep() != 3) { + postAndAddMessage(message); + } + break; + + case 1005: + EventBus.getDefault().post(message); + if (text != null && text.getText() != null) { + addSingleMessage(message); + } + break; + + default: + EventBus.getDefault().post(message); + break; + } + } + + private EMMessageInfo createMessageInfoIfNeeded(RoomMessageEvent message) { + int msgType = message.getMsgType(); + RoomMessageEvent.T text = message.getText(); + + switch (msgType) { + case 1001: + case 1002: + case 123: + case 1003: + case 1004: + case 1000: + case 1: + case 1030: + case 1033: + case 1032: + case 1039: + case 1049: + return new EMMessageInfo(message); + + case 1005: + if (text != null && text.getText() != null) { + return new EMMessageInfo(message); + } + break; + + case 1038: + return new EMMessageInfo(message); + } + + return null; + } + + private void addSingleMessage(RoomMessageEvent message) { + if (easeChatAdapter != null) { + easeChatAdapter.addData(new EMMessageInfo(message)); + scrollToBottomIfNeed(); + } + } + + private void postAndAddMessage(RoomMessageEvent message) { + EventBus.getDefault().post(message); + addSingleMessage(message); + } + + // 在类的字段部分添加以下内容 + private static final int MAX_MESSAGE_COUNT = 500; // 限制最大消息数 + + // 优化 scrollToBottomIfNeed 方法 + private void scrollToBottomIfNeed() { + if (isBottom && mBinding.recycleView != null && easeChatAdapter != null) { + int itemCount = easeChatAdapter.getItemCount(); + if (itemCount > 0) { + mBinding.recycleView.scrollToPosition(itemCount - 1); + } + } else { + count++; + if (mBinding.tvCount != null) { + mBinding.tvCount.setText(count + "条新消息"); + mBinding.tvCount.setVisibility(View.VISIBLE); + } + + // 当未读消息过多时,限制数量显示 + if (count > 99) { + if (mBinding.tvCount != null) { + mBinding.tvCount.setText("99+条新消息"); + } + } + } + } + + + @Subscribe(threadMode = ThreadMode.MAIN) public void roomJoinMount(RoomSettingEvent roomSetting) { if (roomSetting == null) { @@ -664,15 +924,15 @@ public class PublicScreenEaseChatFragment extends BaseMvpFragment