修改MQTT使用方式

修改bug
修改盲盒布局
This commit is contained in:
2025-09-04 01:10:07 +08:00
parent c90b44ebf6
commit 830913e001
78 changed files with 1027 additions and 322 deletions

View File

@@ -31,6 +31,7 @@ import com.xscm.moduleutil.event.AppLifecycleEvent;
import com.xscm.moduleutil.interfaces.AppLifecycleUtil;
import com.xscm.moduleutil.listener.MessageListenerSingleton;
import com.xscm.moduleutil.rtc.AgoraManager;
import com.xscm.moduleutil.service.MqttConnect;
import com.xscm.moduleutil.service.MyMqttService;
import com.xscm.moduleutil.utils.SpUtil;
import com.xscm.moduleutil.utils.UtilConfig;
@@ -50,6 +51,7 @@ import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.qcloud.tuicore.TUILogin;
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.greenrobot.eventbus.EventBus;
import java.lang.reflect.Method;
@@ -84,7 +86,7 @@ public class CommonAppContext extends MultiDexApplication {
public String playName;
private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
private ScheduledExecutorService scheduledExecutorServiceRoom = null;
private MqttConnect mqttConnect=null;
@Override
public void onCreate() {
super.onCreate();
@@ -110,12 +112,15 @@ public class CommonAppContext extends MultiDexApplication {
MessageListenerSingleton.getInstance();
CrashReport.initCrashReport(this, "ac3ed4d89f", true);/*bugly初始化*/
// // 启动 MQTT 服务
Intent mqttServiceIntent = new Intent(this, MyMqttService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(mqttServiceIntent);
} else {
startService(mqttServiceIntent);
}
// Intent mqttServiceIntent = new Intent(this, MyMqttService.class);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// startForegroundService(mqttServiceIntent);
// } else {
// startService(mqttServiceIntent);
// }
mqttConnect=MqttConnect.getInstance(this,"tcp://62.234.12.147","android-"+ MqttClient.generateClientId());
mqttConnect.mqttClient();
// 每次启动应用时重置状态
SpUtil.getInstance().setBooleanValue("youth_model_shown", false);

View File

@@ -159,7 +159,7 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment<GiftLotteryPresente
requireActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenHeight = displayMetrics.heightPixels;
// 设置高度为屏幕高度的100%(全屏)
int heightInPx = (int) (screenHeight * 0.9);
int heightInPx = (int) (screenHeight * 0.79);
;
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, heightInPx);
window.setBackgroundDrawableResource(android.R.color.transparent);
@@ -304,6 +304,7 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment<GiftLotteryPresente
int id = view.getId();
if (id == R.id.ll_one) {
if (!isDrawing) {
isDrawing=true;
init(1);
startType = 1;
MvpPre.drawGiftList(giftBagId, userIds, roomId, "1");
@@ -313,14 +314,17 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment<GiftLotteryPresente
}
} else if (id == R.id.ll_ten) {
if (!isDrawing) {
isDrawing=true;
init(2);
startType = 2;
MvpPre.drawGiftList(giftBagId, userIds, roomId, "10");
} else {
com.hjq.toast.ToastUtils.show("正在抽奖中...");
}
} else if (id == R.id.ll_hundred) {//抽奖100次
if (!isDrawing) {
isDrawing=true;
init(3);
startType = 3;
MvpPre.drawGiftList(giftBagId, userIds, roomId, "100");
@@ -504,6 +508,7 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment<GiftLotteryPresente
MvpPre.giftSend(blind_box_turntable_id);
MvpPre.wallet();
isDrawing = false;
stopFastAnimate();
return;
}
@@ -524,7 +529,7 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment<GiftLotteryPresente
}
public void stopFastAnimate() {
isDrawing = false;
if (handler != null) {
// 移除特定的 Runnable更精确
if (timerRunnable != null) {
@@ -719,7 +724,7 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment<GiftLotteryPresente
playSound("draw.mp3");
// 不要设置isDrawing=true这会影响动画控制
MvpPre.wallet();
isDrawing=false;
MvpPre.giftSend(blind_box_turntable_id);
}
giftCardView.bindGiftData(giftBean);
@@ -731,6 +736,7 @@ public class GiftLotteryDialog extends BaseMvpDialogFragment<GiftLotteryPresente
startFastAnimate();
}
}
}
@Override

View File

@@ -772,6 +772,14 @@ public class AgoraManager {
super.onFirstRemoteAudioFrame(uid, elapsed);
Log.i("RoomCabinFragment", "onFirstRemoteAudioFrame: uid->" + uid);
}
// 可继续扩展其他回调...
@Override
public void onFirstRemoteVideoFrame(int uid, int width, int height, int elapsed) {
super.onFirstRemoteVideoFrame(uid, width, height, elapsed);
SurfaceView renderView = new SurfaceView(context);
SurfaceEvent surfaceEvent = new SurfaceEvent();
surfaceEvent.setSurfaceView(renderView);
@@ -779,7 +787,6 @@ public class AgoraManager {
rtcEngine.setupRemoteVideo(new VideoCanvas(renderView, Constants.RENDER_MODE_FIT, uid));
EventBus.getDefault().post(surfaceEvent);
}
// 可继续扩展其他回调...
@Override
public void onRemoteVideoStateChanged(int uid, int state, int reason, int elapsed) {

View File

@@ -0,0 +1,205 @@
package com.xscm.moduleutil.service;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import com.blankj.utilcode.util.LogUtils;
import com.google.android.gms.common.api.Api;
import com.xscm.moduleutil.utils.logger.DataLogger;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import java.util.ArrayList;
public class MqttConnect {
private String HOST;
private String Tag = "MQTT";
private String clientId = "";
private static MqttClient mqttClient = null;
private Context context;
// 订阅主题
public static String shutdown = "";
public static String update_app = "";
Handler handler = new Handler(Looper.getMainLooper());
String[] topic;
int[] qos = {1,2,3,0,0,0,0,0,0,0,0,0,0}; // 消息质量
private static MqttConnect instance;
public MqttConnect(Context context, String host, String clientId) {
this.HOST = host;
this.context = context;
this.clientId = clientId;
// 这里是你自己需要订阅的主题
shutdown = "qx_room_topic"; // 关机
update_app = "qx_xunlehui"; // 发送更新APP
ArrayList<String> topicList = new ArrayList<>();
topicList.add(shutdown);
topicList.add(update_app);
topic = topicList.toArray(new String[0]);
}
/**
* 单列模式,只能实例化一次
* @param context
* @param host
* @param clientId
* @return
*/
public static synchronized MqttConnect getInstance(Context context, String host, String clientId) {
if (instance == null) {
instance = new MqttConnect(context, host, clientId);
}
return instance;
}
/**
* 客户端connect连接mqtt服务器
**/
public void mqttClient()
{
close();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
MqttConnectOptions options = mqttConnectOptions();
mqttClient.setCallback(new MqttInitCallback(context, HOST, clientId));
mqttClient.connect(options);
// sub(topic,qos);
sub(shutdown);
sub(update_app);
uiTip("MQTT连接成功");
}catch (MqttException e){
uiTip("MQTT连接失败,准备重连。。。:"+e.getMessage());
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.e(Tag,"开始重连。。。");
mqttClient();
}
},3000);
}
}
},200);
}
/**
* 在主线程弹出消息
* @param msg
*/
private void uiTip(String msg){
Log.d(Tag,msg);
handler.post(new Runnable() {
@Override
public void run() {
// Toast.makeText(context.getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
LogUtils.e("mqtt","连接成功");
}
});
}
/**
* MQTT连接参数设置
*/
private MqttConnectOptions mqttConnectOptions()
throws MqttException {
mqttClient = new MqttClient(HOST, clientId, new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setUserName("public");
options.setConnectionTimeout(10);
options.setCleanSession(true);
options.setConnectionTimeout(10);
options.setKeepAliveInterval(10);
return options;
}
/**
* 关闭MQTT连接
*/
public void close(){
if(mqttClient != null && mqttClient.isConnected()){
try {
mqttClient.close();
mqttClient.disconnect();
mqttClient = null;
} catch (MqttException e) {
Log.e(Tag,"关闭MQTT连接报错"+e.getMessage());
}
}else {
Log.d(Tag,"Mqtt已关闭");
}
}
/**
* 向某个主题发布消息 默认qos1
*/
public static void pub(String topic, String msg) throws MqttException {
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setPayload(msg.getBytes());
MqttTopic mqttTopic = mqttClient.getTopic(topic);
MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
token.waitForCompletion();
}
/**
* 向某个主题发布消息
*
* @param topic: 发布的主题
* @param msg: 发布的消息
* @param qos: 消息质量 Qos0、1、2
*/
public void pub(String topic, String msg, int qos) throws MqttException {
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setQos(qos);
mqttMessage.setPayload(msg.getBytes());
MqttTopic mqttTopic = mqttClient.getTopic(topic);
MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
token.waitForCompletion();
}
/**
* 订阅某一个主题 此方法默认的的Qos等级为1
*
* @param topic 主题
*/
public void sub(String topic){
try {
mqttClient.subscribe(topic);
} catch (MqttException e) {
Log.e(Tag,"MQTT主题订阅失败" + e.getMessage());
}
}
/**
* 订阅某一个主题可携带Qos
*
* @param topic 所要订阅的主题
* @param qos
* 消息质量0最多发送一次不保证消息能够到达接收端也不负责重发
* 1至少发送一次确保消息能够到达接收端但可能会导致消息重复
* 2确保消息恰好被接收一次
*/
public void sub(String[] topic, int[] qos){
try {
mqttClient.subscribe(topic, qos);
}catch (MqttException e){
Log.e(Tag,"订阅主题失败:"+e.getMessage());
}
}
// 原文链接https://blog.csdn.net/Fyx1987496919/article/details/140516525
}

View File

@@ -0,0 +1,104 @@
package com.xscm.moduleutil.service;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.orhanobut.logger.Logger;
import com.xscm.moduleutil.bean.XLHBean;
import com.xscm.moduleutil.event.RoomGiftRunable;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.greenrobot.eventbus.EventBus;
public class MqttInitCallback implements MqttCallback {
private String Tag = "MqttInitCallback";
private String HOST;
private String clientId = "";
private MqttConnect mqttConnect = null;
private Context context = null;
MqttInitCallback(Context context, String host, String clientId){
this.context = context;
this.HOST = host;
this.clientId = clientId;
}
/**
* 连接丢失
*/
@Override
public void connectionLost(Throwable cause) {
Log.d(Tag,"mqtt连接断开,执行重连");
mqttConnect = MqttConnect.getInstance(context, HOST, clientId);
mqttConnect.mqttClient();
}
/**
* subscribe订阅后得到的消息会执行到这里
*/
@Override
public void messageArrived(String topic, MqttMessage message){
// Log.d(Tag,"topic");
// Log.d(Tag,topic);
String messageStr = message.toString();
Logger.e("MQTT", "收到的消息", "主题:" + topic + " 收到的消息:" + messageStr);
if (topic.equals("qx_room_topic")) {
receiveMessage(topic, messageStr);
} else if (topic.equals("qx_xunlehui")) {
receiveXlhMessage(messageStr);
}
}
private void receiveMessage(String topic, String data) {
try {
JSONObject jsonObject = JSON.parseObject(data);
int type = jsonObject.getIntValue("type");
String message = jsonObject.getString("msg");
// 将事件处理放到主线程执行
new Handler(Looper.getMainLooper()).post(() -> {
processMessageType(type, message);
});
} catch (Exception e) {
Log.e("MQTT", "解析MQTT消息异常", e);
}
}
private void processMessageType(int type, String message) {
switch (type) {
case 5019://推送所有人-横幅礼物通知
new RoomGiftRunable(message).run();
break;
}
}
private void receiveXlhMessage(String messageStr) {
try {
JSONObject jsonObject = JSON.parseObject(messageStr);
int type = jsonObject.getIntValue("type");
String message = jsonObject.getString("msg");
XLHBean xlhBean=JSON.parseObject(message, XLHBean.class);
// 将事件处理放到主线程执行
new Handler(Looper.getMainLooper()).post(() -> {
// processMessageType(type, message);
EventBus.getDefault().post(xlhBean);
});
} catch (Exception e) {
Log.e("MQTT", "解析MQTT消息异常", e);
}
}
/**
* publish发布成功后会执行到这里
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
// 原文链接https://blog.csdn.net/Fyx1987496919/article/details/140516525
}

View File

@@ -129,9 +129,10 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
public enum RenderType {SVGA, MP4}
private RenderType renderType;
private ExoPlayer exoPlayer;
private PlayerView playerView;
// private ExoPlayer exoPlayer;
// private PlayerView playerView;
private SVGAImageView svgaSurface;
private SVGAImageView svgaSurface2;
private GLSurfaceView glSurfaceView;
private final Handler mainHandler = new Handler(Looper.getMainLooper());
private ChannelSplitRenderer1 renderer;
@@ -168,16 +169,20 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
private void initViews() {
// if (isDestroyed) return;
// 初始化 ExoPlayer View
playerView = new PlayerView(getContext());
playerView.setUseController(false);
playerView.setVisibility(View.GONE);
addView(playerView);
// playerView = new PlayerView(getContext());
// playerView.setUseController(false);
// playerView.setVisibility(View.GONE);
// addView(playerView);
// 初始化 SVGA View
svgaSurface = new SVGAImageView(getContext());
svgaSurface.setVisibility(View.GONE);
addView(svgaSurface);
svgaSurface2 = new SVGAImageView(getContext());
svgaSurface2.setVisibility(View.GONE);
addView(svgaSurface2);
// // 初始化 GLSurfaceView
// glSurfaceView = new GLSurfaceView(getContext());
// glSurfaceView.setEGLContextClientVersion(2);
@@ -189,12 +194,13 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
// 初始化 ExoPlayer
// if (!isDestroyed) {
try {
exoPlayer = new ExoPlayer.Builder(getContext()).build();
playerView.setPlayer(exoPlayer);
} catch (Exception e) {
LogUtils.e("AvatarFrameView", "Failed to initialize ExoPlayer: " + e.getMessage());
}
// try {
// exoPlayer = new ExoPlayer.Builder(getContext()).build();
// playerView.setPlayer(exoPlayer);
// } catch (Exception e) {
// LogUtils.e("AvatarFrameView", "Failed to initialize ExoPlayer: " + e.getMessage());
// }
// }
if (mBinding != null) {
@@ -748,34 +754,34 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
}
}
private void loadMP4(String url) {
svgaSurface.setVisibility(View.GONE);
playerView.setVisibility(View.GONE);
glSurfaceView.setVisibility(View.VISIBLE);
glSurfaceView.onResume();
glSurfaceView.requestRender();
// 使用 post 确保 GLSurfaceView 已完成 layout
glSurfaceView.post(() -> {
Log.d("@@@", "GLSurfaceView size after layout: " + glSurfaceView.getWidth() + "x" + glSurfaceView.getHeight());
glSurfaceView.onResume();
glSurfaceView.requestRender();
renderer.setOnSurfaceTextureReadyListener(surfaceTexture -> {
mainHandler.post(() -> {
Surface surface = new Surface(surfaceTexture);
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(url));
exoPlayer.setMediaItem(mediaItem);
exoPlayer.setVideoSurface(surface);
exoPlayer.prepare();
exoPlayer.play();
Log.d("@@@", "ExoPlayer state after play: " + exoPlayer.getPlaybackState());
});
});
});
}
// private void loadMP4(String url) {
// svgaSurface.setVisibility(View.GONE);
// playerView.setVisibility(View.GONE);
//
// glSurfaceView.setVisibility(View.VISIBLE);
// glSurfaceView.onResume();
// glSurfaceView.requestRender();
// // 使用 post 确保 GLSurfaceView 已完成 layout
// glSurfaceView.post(() -> {
// Log.d("@@@", "GLSurfaceView size after layout: " + glSurfaceView.getWidth() + "x" + glSurfaceView.getHeight());
//
// glSurfaceView.onResume();
// glSurfaceView.requestRender();
//
// renderer.setOnSurfaceTextureReadyListener(surfaceTexture -> {
// mainHandler.post(() -> {
// Surface surface = new Surface(surfaceTexture);
//
// MediaItem mediaItem = MediaItem.fromUri(Uri.parse(url));
// exoPlayer.setMediaItem(mediaItem);
// exoPlayer.setVideoSurface(surface);
// exoPlayer.prepare();
// exoPlayer.play();
// Log.d("@@@", "ExoPlayer state after play: " + exoPlayer.getPlaybackState());
// });
// });
// });
// }
private void clearPrevious() {
// if (isDestroyed) return;
@@ -790,25 +796,25 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
}
try {
// 停止并清理 ExoPlayer
if (exoPlayer != null) {
try {
exoPlayer.stop(); // 这里可能会在错误线程中调用
exoPlayer.clearVideoSurface();
} catch (Exception e) {
Logger.e("Error stopping ExoPlayer: " + e.getMessage());
// 如果在错误线程中,切换到主线程重试
mainHandler.post(() -> {
try {
if (exoPlayer != null) {
exoPlayer.stop();
exoPlayer.clearVideoSurface();
}
} catch (Exception ex) {
Logger.e("Error stopping ExoPlayer on main thread: " + ex.getMessage());
}
});
}
}
// if (exoPlayer != null) {
// try {
// exoPlayer.stop(); // 这里可能会在错误线程中调用
// exoPlayer.clearVideoSurface();
// } catch (Exception e) {
// Logger.e("Error stopping ExoPlayer: " + e.getMessage());
// // 如果在错误线程中,切换到主线程重试
// mainHandler.post(() -> {
// try {
// if (exoPlayer != null) {
// exoPlayer.stop();
// exoPlayer.clearVideoSurface();
// }
// } catch (Exception ex) {
// Logger.e("Error stopping ExoPlayer on main thread: " + ex.getMessage());
// }
// });
// }
// }
// 停止并清理 SVGA 动画
if (svgaSurface != null && svgaSurface.getDrawable() instanceof SVGADrawable) {
SVGADrawable drawable = (SVGADrawable) svgaSurface.getDrawable();
@@ -821,7 +827,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
}
// 隐藏所有视图
if (playerView != null) playerView.setVisibility(View.GONE);
// if (playerView != null) playerView.setVisibility(View.GONE);
if (svgaSurface != null) svgaSurface.setVisibility(View.GONE);
mBinding.playView.setVisibility(View.GONE);
@@ -867,7 +873,7 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
new Thread(() -> {
try {
// 在后台线程处理文件操作和大对象清理
performHeavyCleanup();
// performHeavyCleanup();
// 回到主线程处理 UI 相关的清理
mainHandler.post(() -> {
@@ -944,22 +950,24 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
}
// 清理 ExoPlayer 资源
if (exoPlayer != null) {
try {
// 使用异步停止避免阻塞
exoPlayer.stop();
exoPlayer.clearVideoSurface();
} catch (Exception e) {
Logger.e(TAG, "Error releasing ExoPlayer resources: " + e.getMessage());
}
}
// if (exoPlayer != null) {
// try {
// // 使用异步停止避免阻塞
// exoPlayer.stop();
// exoPlayer.clearVideoSurface();
// } catch (Exception e) {
// Logger.e(TAG, "Error releasing ExoPlayer resources: " + e.getMessage());
// }
// }
// 清理 SVGA 资源
if (svgaSurface != null) {
try {
svgaSurface.pauseAnimation();
svgaSurface.clearAnimation();
svgaSurface.setImageDrawable(null);
// svgaSurface.pauseAnimation();
// svgaSurface.clearAnimation();
// svgaSurface.setImageDrawable(null);
svgaSurface.stopAnimation(true);
svgaSurface.clear();
} catch (Exception e) {
Logger.e(TAG, "Error releasing SVGA resources: " + e.getMessage());
}
@@ -976,10 +984,10 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
Logger.d("AvatarFrameView", "Public release called");
// if (isDestroyed) return;
// 确保在主线程中执行
if (Looper.myLooper() != Looper.getMainLooper()) {
mainHandler.post(this::release);
return;
}
// if (Looper.myLooper() != Looper.getMainLooper()) {
// mainHandler.post(this::release);
// return;
// }
isDestroyed = true;
try {
@@ -990,28 +998,28 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
releaseResources();
// 延迟清理 ExoPlayer避免主线程阻塞
mainHandler.postDelayed(() -> {
if (exoPlayer != null) {
try {
exoPlayer.release();
} catch (Exception e) {
Logger.e(TAG, "Error releasing ExoPlayer: " + e.getMessage());
}
exoPlayer = null;
}
}, 50);
// mainHandler.postDelayed(() -> {
// if (exoPlayer != null) {
// try {
// exoPlayer.release();
// } catch (Exception e) {
// Logger.e(TAG, "Error releasing ExoPlayer: " + e.getMessage());
// }
// exoPlayer = null;
// }
// }, 50);
// 延迟清理其他资源
mainHandler.postDelayed(() -> {
// 清理 PlayerView
if (playerView != null) {
try {
playerView.setPlayer(null);
} catch (Exception e) {
Logger.e(TAG, "Error releasing PlayerView: " + e.getMessage());
}
playerView = null;
}
// if (playerView != null) {
// try {
// playerView.setPlayer(null);
// } catch (Exception e) {
// Logger.e(TAG, "Error releasing PlayerView: " + e.getMessage());
// }
// playerView = null;
// }
// 清理 binding
if (mBinding != null) {
@@ -1020,25 +1028,12 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
}, 100);
// 清理 SVGAImageView
if (svgaSurface != null) {
try {
svgaSurface.pauseAnimation();
svgaSurface.clearAnimation();
svgaSurface.setImageDrawable(null);
} catch (Exception e) {
LogUtils.e(TAG, "Error releasing SVGAImageView: " + e.getMessage());
}
svgaSurface = null;
}
// 清理 binding
if (mBinding != null) {
mBinding = null;
}
// 清理队列
playQueue.clear();
} catch (Exception e) {
LogUtils.e(TAG, "Error in AvatarFrameView release: " + e.getMessage());
@@ -1083,4 +1078,56 @@ public class AvatarFrameView extends FrameLayout implements IAnimListener {
// mBinding.image.stopAnimation();
// }
}
/**
* 开始循环播放SVGA动画
*/
public void startLoopingSvga(String assetName) {
if (Looper.myLooper() != Looper.getMainLooper()) {
mainHandler.post(() -> startLoopingSvga(assetName));
return;
}
try {
clearPrevious(); // 清除之前的动画
svgaSurface.setVisibility(View.VISIBLE);
new SVGAParser(getContext()).decodeFromAssets(assetName, new SVGAParser.ParseCompletion() {
@Override
public void onComplete(SVGAVideoEntity svgaVideoEntity) {
SVGADrawable drawable = new SVGADrawable(svgaVideoEntity);
svgaSurface.setImageDrawable(drawable);
svgaSurface.setLoops(0); // 0表示无限循环
svgaSurface.startAnimation();
}
@Override
public void onError() {
Log.e(TAG, "解析SVGA文件失败: " + assetName);
}
});
} catch (Exception e) {
Log.e(TAG, "播放SVGA动画出错", e);
}
}
/**
* 停止并销毁当前SVGA动画
*/
public void stopSvga() {
if (Looper.myLooper() != Looper.getMainLooper()) {
mainHandler.post(() -> stopSvga());
return;
}
try {
if (svgaSurface2 != null) {
svgaSurface2.stopAnimation(true);
svgaSurface2.setImageDrawable(null);
svgaSurface2.setVisibility(View.GONE);
}
} catch (Exception e) {
Log.e(TAG, "停止SVGA动画出错", e);
}
}
}

View File

@@ -27,7 +27,6 @@ import com.xscm.moduleutil.bean.room.RoomPitBean;
import com.xscm.moduleutil.bean.room.RoomWheatModel;
import com.xscm.moduleutil.event.RoomBanWheatEvent;
import com.xscm.moduleutil.event.RoomBeckoningEvent;
import com.xscm.moduleutil.event.RoomCardiacValueChangedEvent;
import com.xscm.moduleutil.event.RoomFaceEvent;
import com.xscm.moduleutil.interfaces.IBaseWheat;
import com.xscm.moduleutil.interfaces.SoundLevelUpdateListener;
@@ -233,14 +232,16 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
if (userId.equals(pitBean.getUser_id())) {
if (soundLevel == 0) {
mIvRipple.post(() -> {
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
mIvRipple.setVisibility(GONE);
});
mIvRipple.setVisibility(GONE);
} else {
mIvRipple.setVisibility(VISIBLE);
mIvRipple.post(() -> {
mIvRipple.startAnimation();
if (!mIvRipple.isAnimating()) {
mIvRipple.startAnimation();
}
iv_on_line.setVisibility(GONE);
// mIvRipple.setSource(getResources().getResourceName(R.raw.ripple3695), 2);
@@ -269,7 +270,9 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
} else {
mIvRipple.setVisibility(VISIBLE);
mIvRipple.post(() -> {
mIvRipple.startAnimation();
if (!mIvRipple.isAnimating()) {
mIvRipple.startAnimation();
}
iv_on_line.setVisibility(GONE);
// mIvRipple.setSource(getResources().getResourceName(R.raw.ripple3695), 2);
@@ -451,7 +454,7 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
// mCharmView.setSex(pitBean.getSex(), pitBean.getUser_id(), pitBean.getXin_dong(), false);
// }
// }
EventBus.getDefault().post(new RoomCardiacValueChangedEvent(pitNumber, pitBean.getCharm()));
// EventBus.getDefault().post(new RoomCardiacValueChangedEvent(pitNumber, pitBean.getCharm()));
}
}
@@ -463,7 +466,7 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
if (mCharmView != null) {
pitBean.setCharm("0");
mCharmView.setSex(pitBean.getSex(), pitBean.getUser_id(), pitBean.getCharm(), true);
EventBus.getDefault().post(new RoomCardiacValueChangedEvent(pitNumber, pitBean.getCharm()));
// EventBus.getDefault().post(new RoomCardiacValueChangedEvent(pitNumber, pitBean.getCharm()));
}
}

View File

@@ -61,7 +61,7 @@ public class RoomDefaultWheatView extends BaseWheatView {
sex = bean.getSex();
if (isOn()) {
//开启声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
mIvRipple.setVisibility(VISIBLE);
mTvName.setText(bean.getNickname());
ImageUtils.loadHeadCC(bean.getAvatar(), mRiv);
@@ -100,7 +100,7 @@ public class RoomDefaultWheatView extends BaseWheatView {
mIvFrame.setVisibility(INVISIBLE);
mIvFace.remove();
//停止声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation( true);
mIvRipple.setVisibility(GONE);
}
if (showSexIcon) {
@@ -112,19 +112,19 @@ public class RoomDefaultWheatView extends BaseWheatView {
mCharmView.setVisibility(VISIBLE);
}
if (pitBean.is_pk() ){
if (pitBean.getUser_id()!=null && !pitBean.getUser_id().equals("0") && !pitBean.getUser_id().isEmpty()) {
if (pitBean.is_pk()) {
if (pitBean.getUser_id() != null && !pitBean.getUser_id().equals("0") && !pitBean.getUser_id().isEmpty()) {
tv_time_pk.setVisibility(VISIBLE);
setSex(pitBean.getCharm(),false);
setSex(pitBean.getCharm(), false);
mCharmView.setVisibility(GONE);
}else {
} else {
tv_time_pk.setVisibility(GONE);
}
// ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mCharmView.getLayoutParams();
// params.width = 35;
// mCharmView.setLayoutParams(params);
}else {
} else {
tv_time_pk.setVisibility(GONE);
mCharmView.setVisibility(VISIBLE);
// ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mCharmView.getLayoutParams();
@@ -134,7 +134,8 @@ public class RoomDefaultWheatView extends BaseWheatView {
// setCardiac(pitBean.getPit_number(), 0.0f);
}
public void setSex( String value, boolean format) {
public void setSex(String value, boolean format) {
if (format) {
tv_time_pk.setText(value);
} else {
@@ -221,17 +222,18 @@ public class RoomDefaultWheatView extends BaseWheatView {
@Override
public void onLocalSoundLevelUpdate(int volume) {
if (volume==0){
mIvRipple.stopAnimation();
if (volume == 0) {
mIvRipple.stopAnimation( true);
} else {
if (pitBean.getUser_id().equals(SpUtil.getUserId()) && closePhone) {
mIvRipple.stopAnimation();
}else {
mIvRipple.stopAnimation( true);
} else {
mIvRipple.post(() -> {
mIvRipple.setVisibility(VISIBLE);
if (!mIvRipple.isAnimating()) {
mIvRipple.startAnimation();
}
mIvRipple.setVisibility(VISIBLE);
});
}
}
@@ -247,4 +249,8 @@ public class RoomDefaultWheatView extends BaseWheatView {
}
@Override
public void unRegister(Object obj) {
}
}

View File

@@ -80,7 +80,7 @@ public class RoomFriendshipWheatView extends BaseWheatView {
sex = bean.getSex();
if (isOn()) {
//开启声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
mIvRipple.setVisibility(VISIBLE);
mTvName.setText(bean.getNickname());
ImageUtils.loadCenterCrop(bean.getAvatar(), mRiv);
@@ -113,7 +113,7 @@ public class RoomFriendshipWheatView extends BaseWheatView {
mIvFrame.setVisibility(INVISIBLE);
mIvFace.remove();
//停止声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation( true);
mIvRipple.setVisibility(GONE);
}
if (showSexIcon) {
@@ -301,6 +301,11 @@ public class RoomFriendshipWheatView extends BaseWheatView {
this.mOnZhulClickListener = listener;
}
@Override
public void unRegister(Object obj) {
}
public interface OnZhulClickListener {
void onZhulClick(RoomFriendshipWheatView view, RoomPitBean pitBean);
}

View File

@@ -57,7 +57,7 @@ public class RoomKtvWheatView extends BaseWheatView {
sex = bean.getSex();
if (isOn()) {
//开启声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
mIvRipple.setVisibility(VISIBLE);
mTvName.setText(bean.getNickname());
ImageUtils.loadHeadCC(bean.getAvatar(), mRiv);
@@ -96,7 +96,7 @@ public class RoomKtvWheatView extends BaseWheatView {
mIvFrame.setVisibility(INVISIBLE);
mIvFace.remove();
//停止声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
mIvRipple.setVisibility(GONE);
}
if (showSexIcon) {
@@ -218,10 +218,10 @@ public class RoomKtvWheatView extends BaseWheatView {
@Override
public void onLocalSoundLevelUpdate(int volume) {
if (volume==0){
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
} else {
if (pitBean.getUser_id().equals(SpUtil.getUserId()) && closePhone) {
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
}else {
mIvRipple.post(() -> {
if (!mIvRipple.isAnimating()) {
@@ -251,4 +251,8 @@ public class RoomKtvWheatView extends BaseWheatView {
}
}
@Override
public void unRegister(Object obj) {
}
}

View File

@@ -68,7 +68,7 @@ public class RoomMakeWheatView extends BaseWheatView {
sex = bean.getSex();
if (isOn()) {
//开启声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
mIvRipple.setVisibility(VISIBLE);
mTvName.setText(bean.getNickname());
ImageUtils.loadHeadCC(bean.getAvatar(), mRiv);
@@ -96,7 +96,7 @@ public class RoomMakeWheatView extends BaseWheatView {
mIvFrame.setVisibility(INVISIBLE);
mIvFace.remove();
//停止声浪
mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
mIvRipple.setVisibility(GONE);
}
if (showSexIcon) {
@@ -211,4 +211,9 @@ public class RoomMakeWheatView extends BaseWheatView {
}
}
}
@Override
public void unRegister(Object obj) {
}
}

View File

@@ -65,7 +65,7 @@ public class RoomSingSongWheatView extends BaseWheatView {
sex = bean.getSex();
pitBean = bean; // 统一使用参数 bean
stopAndClearAnimation(); // 清理之前的动画资源
if (isOn()) {
handleOnState(bean);
} else {
@@ -78,7 +78,7 @@ public class RoomSingSongWheatView extends BaseWheatView {
}
private void handleOnState(RoomPitBean bean) {
stopAndClearAnimation(); // 清理之前的动画资源
mIvRipple.setVisibility(VISIBLE);
mTvName.setText(bean.getNickname());
ImageUtils.loadHeadCC(bean.getAvatar(), mRiv);
@@ -96,7 +96,6 @@ public class RoomSingSongWheatView extends BaseWheatView {
}
private void handleOffState(RoomPitBean bean) {
stopAndClearAnimation(); // 下麦时停止并清理动画
mTvName.setText(getPitNumberText());
if (showBoss && TextUtils.equals(WHEAT_BOSS, pitNumber)) {
@@ -261,9 +260,10 @@ public class RoomSingSongWheatView extends BaseWheatView {
// 停止并清理动画资源
private void stopAndClearAnimation() {
if (mIvRipple != null) {
mIvRipple.stopAnimation();
// mIvRipple.stopAnimation();
mIvRipple.stopAnimation(true);
// 清理SVGA资源避免内存泄漏
mIvRipple.clear();
// mIvRipple.clear();
}
}
@@ -281,28 +281,23 @@ public class RoomSingSongWheatView extends BaseWheatView {
@Override
public void onLocalSoundLevelUpdate(int volume) {
if (mIvRipple == null) {
return;
}
if (volume == 0) {
if (mIvRipple != null) {
mIvRipple.stopAnimation();
}
mIvRipple.setVisibility(GONE);
mIvRipple.stopAnimation(true);
} else {
// 增加空指针检查
if (pitBean != null && pitBean.getUser_id() != null &&
pitBean.getUser_id().equals(SpUtil.getUserId()) && closePhone) {
if (mIvRipple != null) {
mIvRipple.stopAnimation();
}
mIvRipple.stopAnimation(true);
} else {
if (mIvRipple != null) {
mIvRipple.post(() -> {
if (mIvRipple != null && !mIvRipple.isAnimating()) {
mIvRipple.startAnimation();
}
if (mIvRipple != null) {
mIvRipple.setVisibility(VISIBLE);
}
});
}
mIvRipple.post(() -> {
mIvRipple.setVisibility(VISIBLE);
mIvRipple.startAnimation();
});
}
}
}
@@ -316,4 +311,9 @@ public class RoomSingSongWheatView extends BaseWheatView {
public void userOffline(int userId, int reason) {
// 暂无实现
}
@Override
public void unRegister(Object obj) {
}
}

View File

@@ -12,6 +12,7 @@ import com.xscm.moduleutil.R;
import com.xscm.moduleutil.bean.UserOnlineStatusBean;
import com.xscm.moduleutil.bean.room.RoomPitBean;
import java.util.ArrayList;
import java.util.List;
/**
@@ -26,6 +27,7 @@ public class WheatLayoutSingManager {
private boolean isSingleMode = false;
private int currentSinglePit = -1;
private RoomSingSongWheatView singleWheatView;
private List<RoomSingSongWheatView> multiWheatViews=new ArrayList<>();
private final int[] pitIndexMap = {9, 10, 1, 2, 3, 4, 5, 6, 7, 8};
@@ -129,6 +131,8 @@ public class WheatLayoutSingManager {
return;
}
multiWheatViews.clear();
int screenWidth = getScreenWidth();
int itemWidth = screenWidth / 4; // 每个控件宽度为屏幕宽度的 1/4
@@ -140,7 +144,7 @@ public class WheatLayoutSingManager {
RoomSingSongWheatView wheatView = new RoomSingSongWheatView(context);
wheatView.pitNumber = String.valueOf(pitNumber);
wheatView.setData(pitList.get(pitNumber - 1));
multiWheatViews.add(wheatView);
LinearLayout.LayoutParams params;
if (i == 0) {
@@ -440,22 +444,30 @@ public class WheatLayoutSingManager {
// 添加资源清理方法
public void release() {
try {
if (multiWheatViews!=null){
for (RoomSingSongWheatView wheatView : multiWheatViews) {
wheatView.releaseResources();
}
}
if (container != null) {
// 清理所有子视图的资源
for (int i = 0; i < container.getChildCount(); i++) {
View child = container.getChildAt(i);
if (child instanceof LinearLayout) {
LinearLayout linearLayout = (LinearLayout) child;
for (int j = 0; j < linearLayout.getChildCount(); j++) {
View view = linearLayout.getChildAt(j);
if (view instanceof RoomSingSongWheatView) {
((RoomSingSongWheatView) view).releaseResources();
}
}
} else if (child instanceof RoomSingSongWheatView) {
((RoomSingSongWheatView) child).releaseResources();
}
}
// for (int i = 0; i < container.getChildCount(); i++) {
// View child = container.getChildAt(i);
// if (child instanceof LinearLayout) {
// LinearLayout linearLayout = (LinearLayout) child;
// for (int j = 0; j < linearLayout.getChildCount(); j++) {
// View view = linearLayout.getChildAt(j);
// if (view instanceof RoomSingSongWheatView) {
// ((RoomSingSongWheatView) view).releaseResources();
// }
// }
// } else if (child instanceof RoomSingSongWheatView) {
// ((RoomSingSongWheatView) child).releaseResources();
// }
// }
container.removeAllViews();
}
} catch (Exception e) {

View File

@@ -19,6 +19,7 @@ import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.activity.WebViewActivity;
import com.xscm.moduleutil.base.CommonAppContext;
import com.xscm.moduleutil.bean.CircleListBean;
import com.xscm.moduleutil.databinding.RoomDialogShareBinding;
import com.xscm.moduleutil.utils.BaseBottomSheetDialog;
@@ -142,12 +143,12 @@ public class ShareDialog extends BaseBottomSheetDialog<RoomDialogShareBinding> {
} else if (R.id.tv_jub == id) {
if (types == 3) {
Intent intent = new Intent(getContext(), WebViewActivity.class);
intent.putExtra("url", "https://vespa.qxmier.com/web/index.html#/pages/feedback/report?id=" + SpUtil.getToken() + "&fromType=" + types + "&fromId=" + bean.getId());
intent.putExtra("url", CommonAppContext.getInstance().getCurrentEnvironment().getH5Url()+"/web/index.html#/pages/feedback/report?id=" + SpUtil.getToken() + "&fromType=" + types + "&fromId=" + bean.getId());
intent.putExtra("title", "举报");
startActivity(intent);
}else if (types == 1){
Intent intent = new Intent(getContext(), WebViewActivity.class);
intent.putExtra("url", "https://vespa.qxmier.com/web/index.html#/pages/feedback/report?id=" + SpUtil.getToken() + "&fromType=" + types + "&fromId=" + bean.getUser_id());
intent.putExtra("url", CommonAppContext.getInstance().getCurrentEnvironment().getH5Url()+"/web/index.html#/pages/feedback/report?id=" + SpUtil.getToken() + "&fromType=" + types + "&fromId=" + bean.getUser_id());
intent.putExtra("title", "举报");
startActivity(intent);
}