修改交友布局
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
import com.xscm.moduleutil.R;
|
||||
import com.xscm.moduleutil.event.MqttBean;
|
||||
import com.xscm.moduleutil.utils.ImageUtils;
|
||||
|
||||
|
||||
public class EMqttService extends Service {
|
||||
private WindowManager windowManager;
|
||||
private View piaoPingView;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (intent != null && intent.hasExtra("mqttBean")) {
|
||||
MqttBean mqttBean = (MqttBean) intent.getSerializableExtra("mqttBean");
|
||||
showPiaoPingMessage(mqttBean);//全局飘屏
|
||||
}
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (piaoPingView != null) {
|
||||
windowManager.removeView(piaoPingView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void showPiaoPingMessage(MqttBean mqttBean) {
|
||||
|
||||
int screenWidth = getResources().getDisplayMetrics().widthPixels;
|
||||
int screenHeight = getResources().getDisplayMetrics().heightPixels;
|
||||
//
|
||||
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
||||
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
//
|
||||
// // 设置 Gravity 为左上角
|
||||
// layoutParams.gravity = Gravity.TOP | Gravity.START;
|
||||
//
|
||||
// // Y 轴随机位置
|
||||
// layoutParams.y = (int) ((Math.random() * (screenHeight - 200)));
|
||||
//
|
||||
// // 初始 X 设为负值,确保 View 在屏幕左侧外
|
||||
// layoutParams.x = -screenWidth;
|
||||
|
||||
// FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
||||
// FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
// FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||
//
|
||||
|
||||
// 设置随机 Y 轴位置
|
||||
// layoutParams.topMargin = (int) (Math.random() * (screenHeight - 200));
|
||||
|
||||
|
||||
piaoPingView = LayoutInflater.from(this).inflate(R.layout.item_piaoping, null);
|
||||
TextView textView = piaoPingView.findViewById(R.id.tv_name);
|
||||
textView.setText(mqttBean.getList().getText());
|
||||
ImageUtils.loadHeadCC(mqttBean.getList().getGift_picture(), piaoPingView.findViewById(R.id.iv_piaoping));
|
||||
TextView tv_time = piaoPingView.findViewById(R.id.tv_num);
|
||||
tv_time.setText(mqttBean.getList().getNumber());
|
||||
windowManager.addView(piaoPingView, layoutParams);
|
||||
|
||||
piaoPingView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
piaoPingView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
|
||||
// 设置锚点为左上角,避免偏移干扰
|
||||
piaoPingView.setPivotX(0);
|
||||
piaoPingView.setPivotY(0);
|
||||
|
||||
// 启动动画:从左外滑入 -> 右外滑出
|
||||
ObjectAnimator animator = ObjectAnimator.ofFloat(
|
||||
piaoPingView,
|
||||
"translationX",
|
||||
0f, // 初始偏移为 0(此时 View 在左侧外)
|
||||
screenWidth // 向右移动整个屏幕宽度
|
||||
);
|
||||
animator.setDuration(2000); // 整个动画的时长为2秒
|
||||
|
||||
// 强制 GPU 渲染
|
||||
piaoPingView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
|
||||
// 延迟显示2秒后开始滑出屏幕的动画
|
||||
piaoPingView.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
animator.start();
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
windowManager.removeView(piaoPingView);
|
||||
stopSelf();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
public enum EmqttState {
|
||||
|
||||
DISCONNECT(0), //断开连接
|
||||
CONNECTED(1),//已连接
|
||||
TOPICS_SUCCESS(2),//订阅成功
|
||||
TOPICS_FAIL(3),//订阅失败
|
||||
CANCEL_TOPICS_SUCCESS(4),//取消订阅成功
|
||||
CANCEL_TOPICS_FAIL(5),//取消订阅失败
|
||||
CLOSE_SUCCESS(6),//关闭成功
|
||||
CLOSE_FAIL(7),
|
||||
;//关闭失败
|
||||
|
||||
private int value;
|
||||
|
||||
EmqttState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.xscm.moduleutil.R;
|
||||
import com.xscm.moduleutil.event.MqttBean;
|
||||
import com.xscm.moduleutil.utils.ImageUtils;
|
||||
|
||||
/**
|
||||
*@author qx
|
||||
*@data 2025/8/8
|
||||
*@description: 全局悬浮框管理类
|
||||
*/
|
||||
public class FloatingWindow {
|
||||
private WindowManager windowManager;
|
||||
private View piaoPingView;
|
||||
|
||||
public FloatingWindow(Context context, MqttBean mqttBean){
|
||||
int screenWidth =context.getResources().getDisplayMetrics().widthPixels;
|
||||
windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
piaoPingView = LayoutInflater.from(context).inflate(R.layout.item_piaoping, null);
|
||||
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
||||
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
|
||||
|
||||
PixelFormat.TRANSLUCENT);
|
||||
|
||||
|
||||
TextView textView = piaoPingView.findViewById(R.id.tv_name);
|
||||
textView.setText(mqttBean.getList().getText());
|
||||
ImageUtils.loadHeadCC(mqttBean.getList().getGift_picture(), piaoPingView.findViewById(R.id.iv_piaoping));
|
||||
TextView tv_time = piaoPingView.findViewById(R.id.tv_num);
|
||||
tv_time.setText(mqttBean.getList().getNumber());
|
||||
windowManager.addView(piaoPingView, layoutParams);
|
||||
|
||||
// piaoPingView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
// @Override
|
||||
// public void onGlobalLayout() {
|
||||
// piaoPingView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
//
|
||||
// // 设置锚点为左上角,避免偏移干扰
|
||||
// piaoPingView.setPivotX(0);
|
||||
// piaoPingView.setPivotY(0);
|
||||
//
|
||||
// // 启动动画:从左外滑入 -> 右外滑出
|
||||
// ObjectAnimator animator = ObjectAnimator.ofFloat(
|
||||
// piaoPingView,
|
||||
// "translationX",
|
||||
// 0f, // 初始偏移为 0(此时 View 在左侧外)
|
||||
// screenWidth // 向右移动整个屏幕宽度
|
||||
// );
|
||||
// animator.setDuration(2000); // 整个动画的时长为2秒
|
||||
//
|
||||
// // 强制 GPU 渲染
|
||||
// piaoPingView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
//
|
||||
// // 延迟显示2秒后开始滑出屏幕的动画
|
||||
// piaoPingView.postDelayed(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// animator.start();
|
||||
// }
|
||||
// }, 2000);
|
||||
//
|
||||
// animator.addListener(new AnimatorListenerAdapter() {
|
||||
// @Override
|
||||
// public void onAnimationEnd(Animator animation) {
|
||||
// windowManager.removeView(piaoPingView);
|
||||
// stopSelf();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
piaoPingView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
piaoPingView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
|
||||
// 获取视图宽度
|
||||
int viewWidth = piaoPingView.getWidth();
|
||||
|
||||
// 设置锚点为左上角
|
||||
piaoPingView.setPivotX(0);
|
||||
piaoPingView.setPivotY(0);
|
||||
|
||||
// 强制 GPU 渲染
|
||||
piaoPingView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
|
||||
// 创建滑入动画:从左外滑入到屏幕左侧
|
||||
ObjectAnimator slideInAnimator = ObjectAnimator.ofFloat(
|
||||
piaoPingView,
|
||||
"translationX",
|
||||
-viewWidth, // 起始位置:屏幕左外
|
||||
0f // 结束位置:屏幕左边缘
|
||||
);
|
||||
slideInAnimator.setDuration(500); // 滑入动画时长0.5秒
|
||||
|
||||
// 创建滑出动画:从当前位置滑出到屏幕右侧外
|
||||
ObjectAnimator slideOutAnimator = ObjectAnimator.ofFloat(
|
||||
piaoPingView,
|
||||
"translationX",
|
||||
0f, // 起始位置:屏幕左边缘
|
||||
screenWidth // 结束位置:屏幕右外
|
||||
);
|
||||
slideOutAnimator.setDuration(500); // 滑出动画时长0.5秒
|
||||
|
||||
// 设置滑出动画监听器
|
||||
slideOutAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
windowManager.removeView(piaoPingView);
|
||||
stopSelf();
|
||||
}
|
||||
});
|
||||
|
||||
// 开始执行动画序列
|
||||
slideInAnimator.start();
|
||||
|
||||
// 滑入完成后延迟2秒执行滑出动画
|
||||
piaoPingView.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
slideOutAnimator.start();
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void stopSelf(){
|
||||
if (piaoPingView != null) {
|
||||
windowManager.removeView(piaoPingView);
|
||||
piaoPingView = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class HandlerUtil extends Handler {
|
||||
|
||||
private static HandlerUtil instance = null;
|
||||
WeakReference<Context> mActivityReference;
|
||||
|
||||
public static HandlerUtil getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new HandlerUtil(context.getApplicationContext());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
HandlerUtil(Context context) {
|
||||
mActivityReference = new WeakReference<>(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
public interface MyEmqttConnectListener {
|
||||
|
||||
void onConnectSuccess();
|
||||
|
||||
void onConnectFailure();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
public interface MyEmqttMesgListener {
|
||||
|
||||
void messageArrived(String topic, String mesg);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
public interface MyEmqttSubscribeListener {
|
||||
|
||||
void onSubscribeSuccess(String topic);
|
||||
|
||||
void onSubscribeFailure();
|
||||
}
|
||||
@@ -0,0 +1,621 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.blankj.utilcode.util.LogUtils;
|
||||
import com.blankj.utilcode.util.ServiceUtils;
|
||||
import com.orhanobut.logger.Logger;
|
||||
import com.xscm.moduleutil.R;
|
||||
import com.xscm.moduleutil.event.RoomGiftRunable;
|
||||
|
||||
import org.eclipse.paho.android.service.MqttAndroidClient;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallback;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
|
||||
public class MyMqttService extends Service implements MyEmqttConnectListener,MyEmqttMesgListener,MyEmqttSubscribeListener{
|
||||
|
||||
private final static String TAG = "lxj";
|
||||
|
||||
private static int qos = 2;
|
||||
// private static String HOST ="tcp://81.70.45.221";//正式
|
||||
private static String HOST ="tcp://47.120.21.132";//测试
|
||||
private static MqttAndroidClient mqttAndroidClient;
|
||||
private MqttConnectOptions mMqttConnectOptions;
|
||||
private static boolean b = true;
|
||||
|
||||
|
||||
private static MyEmqttConnectListener mMyEmqttConnectListener;
|
||||
private static MyEmqttMesgListener mMyEmqttMesgListener;
|
||||
private static MyEmqttSubscribeListener mMyEmqttSubscribeListener;
|
||||
|
||||
private static final String TOPIC_BOSS = "qx_room_topic";
|
||||
private static final int NOTIFICATION_ID = 1;
|
||||
|
||||
|
||||
// 添加后台线程处理
|
||||
private HandlerThread mqttHandlerThread;
|
||||
private Handler mqttHandler;
|
||||
private ExecutorService messageExecutorService;
|
||||
|
||||
// 添加连接重试限制
|
||||
private static final int MAX_RETRY_ATTEMPTS = 5;
|
||||
private int retryCount = 0;
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // API 31+
|
||||
// 设置前台服务类型为 "connectedDevice" 或其他合适类型
|
||||
setForegroundServiceBehavior(ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST);
|
||||
}
|
||||
// ⚠️ 必须在这个方法开始就调用 startForeground()
|
||||
Notification notification = createNotification();
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
private void setForegroundServiceBehavior(int foregroundServiceTypeManifest) {
|
||||
// 空实现,仅用于兼容性处理
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// 创建专用的HandlerThread处理MQTT操作
|
||||
mqttHandlerThread = new HandlerThread("MqttServiceThread");
|
||||
mqttHandlerThread.start();
|
||||
mqttHandler = new Handler(mqttHandlerThread.getLooper());
|
||||
|
||||
// 创建线程池处理消息
|
||||
messageExecutorService = Executors.newCachedThreadPool();
|
||||
try {
|
||||
init();
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Notification createNotification() {
|
||||
// 创建你的前台通知
|
||||
// Notification.Builder builder = null;
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// builder = new Notification.Builder(this, "channel_id")
|
||||
// .setContentTitle("MQTT Service")
|
||||
// .setSmallIcon(R.mipmap.default_avatar);
|
||||
// }
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// NotificationChannel channel = new NotificationChannel(
|
||||
// "channel_id", "MQTT Channel",
|
||||
// NotificationManager.IMPORTANCE_LOW);
|
||||
// NotificationManager manager = getSystemService(NotificationManager.class);
|
||||
// manager.createNotificationChannel(channel);
|
||||
// }
|
||||
// return builder.build();
|
||||
|
||||
// 创建你的前台通知
|
||||
Notification.Builder builder = null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
builder = new Notification.Builder(this, "mqtt_channel")
|
||||
.setContentTitle("消息服务")
|
||||
.setContentText("正在接收实时消息")
|
||||
.setSmallIcon(R.mipmap.default_avatar);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(
|
||||
"mqtt_channel", "MQTT Channel",
|
||||
NotificationManager.IMPORTANCE_LOW);
|
||||
NotificationManager manager = getSystemService(NotificationManager.class);
|
||||
if (manager != null) {
|
||||
manager.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
return builder != null ? builder.build() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启服务
|
||||
*/
|
||||
public static void startService(Context mContext) {
|
||||
b = true;
|
||||
boolean serviceRunning = ServiceUtils.isServiceRunning(MyMqttService.class.getCanonicalName());
|
||||
if (!serviceRunning) {
|
||||
mContext.startService(new Intent(mContext, MyMqttService.class));
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopService(Context context) {
|
||||
b = false;
|
||||
boolean serviceRunning = ServiceUtils.isServiceRunning(MyMqttService.class.getCanonicalName());
|
||||
if (serviceRunning) {
|
||||
try {
|
||||
context.stopService(new Intent(context, MyMqttService.class));
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to stop MQTT service", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发布 (模拟其他客户端发布消息)
|
||||
*
|
||||
* @param message 消息
|
||||
*/
|
||||
public static void publish(String topic, String message) throws MqttException {
|
||||
if (mqttAndroidClient == null) {
|
||||
Logger.e(TAG, "mqttAndroidClient is null", "发送失败");
|
||||
return;
|
||||
}
|
||||
//参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
|
||||
IMqttDeliveryToken publish = mqttAndroidClient.publish(topic, message.getBytes(), qos, false);
|
||||
publish.setActionCallback(new IMqttActionListener() {
|
||||
@Override
|
||||
public void onSuccess(IMqttToken asyncActionToken) {
|
||||
Logger.e(TAG, "发送消息", "发送成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
|
||||
Logger.e(TAG, "发送消息", "发送失败");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static void subscribe(String topic) {
|
||||
try {
|
||||
if (mqttAndroidClient.isConnected()) {
|
||||
IMqttToken subToken = mqttAndroidClient.subscribe(topic, qos);
|
||||
subToken.setActionCallback(new IMqttActionListener() {
|
||||
@Override
|
||||
public void onSuccess(IMqttToken asyncActionToken) {
|
||||
if (mMyEmqttSubscribeListener != null) {
|
||||
mMyEmqttSubscribeListener.onSubscribeSuccess(topic);
|
||||
}
|
||||
Logger.e(TAG, "订阅成功:" + topic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IMqttToken asyncActionToken,
|
||||
Throwable exception) {
|
||||
if (!TOPIC_BOSS.equals(topic) && mMyEmqttSubscribeListener != null) {
|
||||
mMyEmqttSubscribeListener.onSubscribeFailure();
|
||||
}
|
||||
Logger.e(TAG, "订阅失败:" + topic);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void cleanSubscribe(String topic) {
|
||||
try {
|
||||
if (mqttAndroidClient.isConnected()) {
|
||||
IMqttToken subToken = mqttAndroidClient.unsubscribe(topic);
|
||||
subToken.setActionCallback(new IMqttActionListener() {
|
||||
@Override
|
||||
public void onSuccess(IMqttToken asyncActionToken) {
|
||||
Logger.e(TAG, "取消成功" + topic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IMqttToken asyncActionToken,
|
||||
Throwable exception) {
|
||||
Logger.e(TAG, "取消失败" + topic);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
private void init() throws MqttException {
|
||||
String CLIENTID = "android-" + MqttClient.generateClientId();
|
||||
mqttAndroidClient = new MqttAndroidClient(this, HOST, CLIENTID);
|
||||
mqttAndroidClient.setCallback(mqttCallback); //设置监听订阅消息的回调
|
||||
mMqttConnectOptions = new MqttConnectOptions();
|
||||
mMqttConnectOptions.setCleanSession(true); //设置是否清除缓存
|
||||
mMqttConnectOptions.setConnectionTimeout(10); //设置超时时间,单位:秒
|
||||
mMqttConnectOptions.setKeepAliveInterval(10); //设置心跳包发送间隔,单位:秒
|
||||
mMqttConnectOptions.setUserName("public"); //设置用户名
|
||||
// mMqttConnectOptions.setPassword(new char[0]); //设置密码
|
||||
mMqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
|
||||
|
||||
if (!mqttAndroidClient.isConnected()) {
|
||||
doClientConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private void doClientConnection() throws MqttException {
|
||||
if (mqttAndroidClient != null && !mqttAndroidClient.isConnected() && isConnectIsNomarl() && b) {
|
||||
mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeConnection() throws MqttException {
|
||||
if (mqttAndroidClient.isConnected()) {
|
||||
IMqttToken disconnect = mqttAndroidClient.disconnect();
|
||||
disconnect.setActionCallback(new IMqttActionListener() {
|
||||
@Override
|
||||
public void onSuccess(IMqttToken asyncActionToken) {
|
||||
Logger.e(TAG, "断开链接", "断开链接成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
|
||||
Logger.e(TAG, "断开链接", "断开链接失败" + exception.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断网络是否连接
|
||||
*/
|
||||
private boolean isConnectIsNomarl() {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
||||
if (info != null && info.isAvailable()) {
|
||||
String name = info.getTypeName();
|
||||
Log.i(TAG, "当前网络名称:" + name);
|
||||
return true;
|
||||
} else {
|
||||
Log.i(TAG, "没有可用网络");
|
||||
/*没有可用网络的时候,延迟3秒再尝试重连*/
|
||||
HandlerUtil.getInstance(this).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
doClientConnection();
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//MQTT是否连接成功的监听
|
||||
private IMqttActionListener iMqttActionListener = new IMqttActionListener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(IMqttToken arg0) {
|
||||
if (mMyEmqttConnectListener != null) {
|
||||
mMyEmqttConnectListener.onConnectSuccess();
|
||||
}
|
||||
Logger.e(TAG, "链接状态:", "链接成功");
|
||||
subscribe(TOPIC_BOSS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IMqttToken arg0, Throwable arg1) {
|
||||
if (mMyEmqttConnectListener != null) {
|
||||
mMyEmqttConnectListener.onConnectFailure();
|
||||
}
|
||||
// if (arg0 instanceof MqttException) {
|
||||
//// Logger.e(TAG, "链接状态:", "链接失败" + ((MqttException) arg1).getMessage());
|
||||
// }
|
||||
HandlerUtil.getInstance(getApplicationContext()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (b) {
|
||||
try {
|
||||
doClientConnection();
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//订阅主题的回调
|
||||
private MqttCallback mqttCallback = new MqttCallback() {
|
||||
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage message) throws Exception {
|
||||
if (mMyEmqttMesgListener != null) {
|
||||
mMyEmqttMesgListener.messageArrived(topic, message.toString());
|
||||
}
|
||||
Logger.e(TAG, "收到的消息", "主题:" + topic + " 收到的消息:" + message.toString());
|
||||
//收到其他客户端的消息后,响应给对方告知消息已到达或者消息有问题等
|
||||
receiveMessage(topic,message.toString());
|
||||
// if (TOPIC_BOSS.equals(topic)) {
|
||||
// EventBus.getDefault().post(new BossMsgEvent(message.toString()));
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken arg0) {
|
||||
LogUtils.e("deliveryComplete---------");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionLost(Throwable arg0) {
|
||||
if (mMyEmqttConnectListener != null) {
|
||||
mMyEmqttConnectListener.onConnectFailure();
|
||||
}
|
||||
Logger.e(TAG, "链接状态:", "链接断开");
|
||||
|
||||
HandlerUtil.getInstance(getApplicationContext()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (b) {
|
||||
try {
|
||||
doClientConnection();
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
private void receiveMessage(String topic, String data) {
|
||||
JSONObject jsonObject = null;
|
||||
try {
|
||||
String newdata = data;//TextLengthUtil.decode(data);
|
||||
jsonObject = JSON.parseObject(newdata);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
int type = jsonObject.getIntValue("type");
|
||||
String message = jsonObject.getString("msg");
|
||||
switch (type) {
|
||||
case 3001://抢糖果游戏
|
||||
break;
|
||||
case 5001://延时一秒推送房间-人气变化
|
||||
break;
|
||||
case 5003://延时一秒推送房间-坐骑进场特效
|
||||
break;
|
||||
case 5004://延时一秒推送房间-爵位用户进场特效
|
||||
break;
|
||||
case 5005://推送房间-上麦申请人数变化
|
||||
Logger.e("环信5005", message);
|
||||
break;
|
||||
case 5007://推送房间-用户是否禁言 1禁言2解禁
|
||||
break;
|
||||
case 5011://推送房间-是否封麦 1封麦2解封
|
||||
break;
|
||||
case 5013://推送房间-清空单个麦位心动值
|
||||
case 5014://推送房间-清空所有麦位心动值
|
||||
break;
|
||||
case 5015://推送房间-设置房间管理员
|
||||
break;
|
||||
case 5016://推送房间-删除房间管理员
|
||||
break;
|
||||
case 5017://用户开关麦
|
||||
// EventBus.getDefault().post(JSON.parseObject(message, WheatVoiceModel.class));
|
||||
break;
|
||||
case 5019://推送所有人-横幅礼物通知c
|
||||
new RoomGiftRunable(message).run();
|
||||
break;
|
||||
case 5020://推送房间-聊天室礼物通知
|
||||
Logger.e("环信5020", message);
|
||||
break;
|
||||
case 5030:
|
||||
case 5021://推送所有人-小猫钓鱼钓到大礼物时通知
|
||||
break;
|
||||
case 5022://推送房间-房间密码变化通知 0取消密码1设置或修改密码
|
||||
break;
|
||||
case 5023://推送房间-房间心动值开关变化通知 1开2关
|
||||
break;
|
||||
case 5024://推送房间-上麦模式变化通知 1自由2排麦
|
||||
break;
|
||||
case 5025://推送房间-修改房间名称
|
||||
break;
|
||||
case 5027://推送房间-周星用户进场特效
|
||||
break;
|
||||
case 5028://推送房间-修改房间背景
|
||||
break;
|
||||
case 5029://推送房间-修改房间公告
|
||||
break;
|
||||
case 5032://推送房间-上麦
|
||||
Logger.e("环信5032", message);
|
||||
break;
|
||||
case 5033://推送房间-下麦
|
||||
Logger.e("环信5033", message);
|
||||
break;
|
||||
case 5034://踢出房间
|
||||
Logger.e("环信5034", message);
|
||||
break;
|
||||
case 5035://推送单独用户-定向推向给上麦的用户
|
||||
break;
|
||||
case 5036://推送房间-用户禁麦 1禁麦2解禁
|
||||
break;
|
||||
case 5037://推送房间-用户进入房间
|
||||
break;
|
||||
case 5038://麦位倒计时
|
||||
break;
|
||||
case 5039://扔骰子
|
||||
break;
|
||||
case 5040://开通守护推送
|
||||
break;
|
||||
case 5041://发送表情
|
||||
break;
|
||||
case 5042://上传即构日志
|
||||
break;
|
||||
case 5043://公屏状态
|
||||
break;
|
||||
case 5044://开球
|
||||
break;
|
||||
case 5045://弃球
|
||||
break;
|
||||
case 5046://亮球
|
||||
break;
|
||||
case 5047://调音
|
||||
break;
|
||||
case 5050://推送
|
||||
break;
|
||||
case 5051://需求变化
|
||||
break;
|
||||
case 5054://房主模式切换
|
||||
break;
|
||||
case 5055://离开房间
|
||||
Logger.e("环信5055", message);
|
||||
break;
|
||||
case 5056://房主加入
|
||||
break;
|
||||
case 5057://房间浇水礼物推送
|
||||
break;
|
||||
case 5058://切换相亲房状态
|
||||
break;
|
||||
case 5059://相亲房礼物动画
|
||||
break;
|
||||
case 5060://房间玫瑰爱神礼物推送
|
||||
break;
|
||||
case 5061://交友房心动值变化
|
||||
Logger.e("环信5061", message);
|
||||
break;
|
||||
case 5062://交友房换麦
|
||||
Logger.e("环信5062", message);
|
||||
// sendEventList(message, RoomPitBean.class);
|
||||
break;
|
||||
case 5063://进入小黑屋
|
||||
Logger.e("环信5063", message);
|
||||
break;
|
||||
case 5064://退出小黑屋
|
||||
Logger.e("环信5064", message);
|
||||
break;
|
||||
case 5065://点击开始后进行提示弹框
|
||||
Logger.e("环信5065", message);
|
||||
break;
|
||||
case 5066://cp对数
|
||||
Logger.e("环信5066", message);
|
||||
break;
|
||||
case 5067://延迟时间
|
||||
Logger.e("环信5067", message);
|
||||
break;
|
||||
case 5068://房间内广播
|
||||
Logger.e("环信5068", message);
|
||||
break;
|
||||
case 5069://房间内换麦
|
||||
Logger.e("环信5069", message);
|
||||
break;
|
||||
case 10001: //房间红包
|
||||
break;
|
||||
case 10002: //雨开始
|
||||
break;
|
||||
case 10003: //打开红包
|
||||
break;
|
||||
case 7001: //奖池进度更新
|
||||
break;
|
||||
case 7002://cp时间到
|
||||
Logger.e("环信7002", message);
|
||||
break;
|
||||
case 5070:
|
||||
Logger.e("环信5070", message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
try {
|
||||
cleanSubscribe(TOPIC_BOSS);
|
||||
if (mqttAndroidClient != null) {
|
||||
mqttAndroidClient.disconnect(); //断开连接
|
||||
mqttAndroidClient.unregisterResources();
|
||||
mqttAndroidClient = null;
|
||||
stopForeground(true); // 停止前台服务
|
||||
}
|
||||
Logger.e(TAG, "服务关闭", "资源释放成功");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
public static void addMyEmqttMesgListener(MyEmqttMesgListener myEmqttMesgListener) {
|
||||
mMyEmqttMesgListener = myEmqttMesgListener;
|
||||
}
|
||||
|
||||
public static void addMyEmqttConnectListener(MyEmqttConnectListener myEmqttConnectListener) {
|
||||
mMyEmqttConnectListener = myEmqttConnectListener;
|
||||
}
|
||||
|
||||
public static void addMyEmqttSubscribeListener(MyEmqttSubscribeListener myEmqttSubscribeListener) {
|
||||
mMyEmqttSubscribeListener = myEmqttSubscribeListener;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onConnectSuccess() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageArrived(String topic, String mesg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribeSuccess(String topic) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribeFailure() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.xscm.moduleutil.bean.RoomSingleton;
|
||||
import com.xscm.moduleutil.http.BaseObserver;
|
||||
import com.xscm.moduleutil.http.RetrofitClient;
|
||||
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
/**
|
||||
* @Author lxj$
|
||||
* @Time 2025-8-6 11:42:49$ $
|
||||
* @Description 每日任务的定时任务单例模式$
|
||||
*/
|
||||
public class MyRoomSingleton {
|
||||
private int count;
|
||||
private static MyRoomSingleton instance;
|
||||
private Handler handler;
|
||||
private String taskId;
|
||||
private boolean isTimerActive;
|
||||
private Context context;
|
||||
|
||||
private MyRoomSingleton() {
|
||||
this.context = context;
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
isTimerActive = false;
|
||||
}
|
||||
|
||||
public static MyRoomSingleton getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new MyRoomSingleton();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void startTimerTask(String taskId) {
|
||||
this.taskId = taskId;
|
||||
count = 0; // 重置计数
|
||||
isTimerActive = true;
|
||||
handler.postDelayed(timerRunnable, 60 * 1000); // 每分钟请求一次接口
|
||||
}
|
||||
|
||||
private Runnable timerRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isTimerActive && count < 5) { // 30分钟任务,每分钟请求一次,共30/60=0.5次,这里假设每分钟请求一次,共30次
|
||||
fetchData();
|
||||
handler.postDelayed(this, 60 * 1000);
|
||||
} else {
|
||||
stopTimerTask(); // 达到最大请求次数后停止定时任务
|
||||
}
|
||||
}
|
||||
};
|
||||
public void stopTimerTask() {
|
||||
handler.removeCallbacksAndMessages(null); // 销毁定时器
|
||||
isTimerActive = false;
|
||||
}
|
||||
public void onExitRoom() {
|
||||
stopTimerTask(); // 退出房间时停止定时任务
|
||||
}
|
||||
public void onEnterRoom(String taskId) {
|
||||
this.taskId = taskId;
|
||||
if (count!=0 ){
|
||||
startTimerTask(taskId); // 进入房间时启动定时任务,延迟为0表示立即执行
|
||||
}else {
|
||||
count = 0; // 重置请求计数
|
||||
startTimerTask(taskId); // 进入房间时启动定时任务,延迟为0表示立即执行
|
||||
}
|
||||
}
|
||||
private void fetchData() {
|
||||
// 这里编写请求接口的代码,例如使用Retrofit或Volley等库
|
||||
// 示例使用Retrofit:
|
||||
RetrofitClient.getInstance().dailyTasksComplete(taskId, new BaseObserver<RoomSingleton>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(RoomSingleton roomSingleton) {
|
||||
count++;
|
||||
// 这里处理请求结果
|
||||
if (roomSingleton.getIs_completed()==1){
|
||||
// 任务完成,可以做一些后续操作
|
||||
stopTimerTask();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.xscm.moduleutil.service;
|
||||
|
||||
import com.xscm.moduleutil.bean.room.RoomClearCardiacAllModel;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
public class RoomClearCardiacRunnable implements Runnable {
|
||||
|
||||
private String data;
|
||||
|
||||
public RoomClearCardiacRunnable(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// RoomClearCardiacModel roomClearCardiacModel = JSON.parseObject(data, RoomClearCardiacModel.class);
|
||||
// if (TextUtils.isEmpty(data)) {
|
||||
EventBus.getDefault().post(new RoomClearCardiacAllModel(data));
|
||||
// } else {
|
||||
// EventBus.getDefault().post(new RoomClearCardiacAllModel());
|
||||
// }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user