android MQTT封装

单纯的记录一下代码

1. build.gradle

implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

2. activity_mian.xml

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <!-- 标题 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="24dp" android:gravity="center" android:text="MQTT客户端演示" android:textColor="@color/colorPrimary" android:textSize="24sp" android:textStyle="bold" /> <!-- 连接控制区 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" app:cardCornerRadius="8dp" app:cardElevation="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp" android:text="连接控制" android:textSize="18sp" android:textStyle="bold" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_connect" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_weight="1" android:text="连接" /> <Button android:id="@+id/btn_disconnect" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_weight="1" android:text="断开" /> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 订阅区 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" app:cardCornerRadius="8dp" app:cardElevation="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp" android:text="主题订阅" android:textSize="18sp" android:textStyle="bold" /> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp"> <EditText android:id="@+id/et_subscribe_topic" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入订阅主题" android:textSize="16sp" /> </com.google.android.material.textfield.TextInputLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_subscribe" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_weight="1" android:text="订阅" /> <Button android:id="@+id/btn_unsubscribe" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_weight="1" android:text="取消订阅" /> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 消息发送区 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" app:cardCornerRadius="8dp" app:cardElevation="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp" android:text="消息发送" android:textSize="18sp" android:textStyle="bold" /> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp"> <EditText android:id="@+id/et_topic" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="目标主题" android:textSize="16sp" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp"> <EditText android:id="@+id/et_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="top" android:hint="消息内容" android:minLines="3" android:textSize="16sp" /> </com.google.android.material.textfield.TextInputLayout> <Button android:id="@+id/btn_send" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送消息" /> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 日志显示区 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardCornerRadius="8dp" app:cardElevation="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp" android:text="日志信息" android:textSize="18sp" android:textStyle="bold" /> <ScrollView android:id="@+id/scroll_view" android:layout_width="match_parent" android:layout_height="200dp" android:background="#f5f5f5" android:padding="8dp"> <TextView android:id="@+id/tv_log" android:layout_width="match_parent" android:layout_height="wrap_content" android:fontFamily="monospace" android:text="等待操作...\n" android:textSize="14sp" /> </ScrollView> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout> </ScrollView>

3. MainActivity.java

package cn.wx.mqtt; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity implements MQTTManager.MQTTCallback { private static final String TAG = "MQTTDemoActivity"; private MQTTService mqttService; private boolean isBound = false; private Handler mainHandler; // UI组件 private Button connectButton; private Button disconnectButton; private Button subscribeButton; private Button unsubscribeButton; private Button sendButton; private EditText topicEditText; private EditText messageEditText; private EditText subscribeTopicEditText; private ScrollView scrollView; private TextView logTextView; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { MQTTService.LocalBinder binder = (MQTTService.LocalBinder) service; mqttService = binder.getService(); isBound = true; // 初始化MQTT管理器 mqttService.initializeMQTT( "tcp://172.16.1.104:1883", // 替换为你的MQTT服务器地址 "AndroidClient_" + System.currentTimeMillis(), "", // 用户名(如有需要) "" // 密码(如有需要) ); // 设置回调 mqttService.getMQTTManager().setCallback(MainActivity.this); updateUIState(); appendLog("服务已连接"); } @Override public void onServiceDisconnected(ComponentName name) { isBound = false; mqttService = null; updateUIState(); appendLog("服务已断开"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainHandler = new Handler(getMainLooper()); initViews(); setupListeners(); bindMQTTService(); } private void initViews() { connectButton = findViewById(R.id.btn_connect); disconnectButton = findViewById(R.id.btn_disconnect); subscribeButton = findViewById(R.id.btn_subscribe); unsubscribeButton = findViewById(R.id.btn_unsubscribe); sendButton = findViewById(R.id.btn_send); topicEditText = findViewById(R.id.et_topic); messageEditText = findViewById(R.id.et_message); subscribeTopicEditText = findViewById(R.id.et_subscribe_topic); scrollView = findViewById(R.id.scroll_view); logTextView = findViewById(R.id.tv_log); // 设置默认值 topicEditText.setText("test"); subscribeTopicEditText.setText("test"); messageEditText.setText("Hello from Android!"); } private void setupListeners() { connectButton.setOnClickListener(v -> connectToMQTT()); disconnectButton.setOnClickListener(v -> disconnectFromMQTT()); subscribeButton.setOnClickListener(v -> subscribeToTopic()); unsubscribeButton.setOnClickListener(v -> unsubscribeFromTopic()); sendButton.setOnClickListener(v -> sendMessage()); } private void bindMQTTService() { Intent intent = new Intent(this, MQTTService.class); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); startService(intent); // 确保服务启动 } private void connectToMQTT() { if (isBound && mqttService != null) { mqttService.getMQTTManager().connect(); } else { showToast("服务未就绪"); } } private void disconnectFromMQTT() { if (isBound && mqttService != null) { mqttService.getMQTTManager().disconnect(); } } private void subscribeToTopic() { String topic = subscribeTopicEditText.getText().toString().trim(); if (topic.isEmpty()) { showToast("请输入主题名称"); return; } if (isBound && mqttService != null) { mqttService.getMQTTManager().subscribe(topic, 1); } } private void unsubscribeFromTopic() { String topic = subscribeTopicEditText.getText().toString().trim(); if (topic.isEmpty()) { showToast("请输入主题名称"); return; } if (isBound && mqttService != null) { mqttService.getMQTTManager().unsubscribe(topic); } } private void sendMessage() { String topic = topicEditText.getText().toString().trim(); String message = messageEditText.getText().toString().trim(); if (topic.isEmpty()) { showToast("请输入主题"); return; } if (message.isEmpty()) { showToast("请输入消息内容"); return; } if (isBound && mqttService != null) { mqttService.getMQTTManager().publish(topic, message, 1, false); appendLog("发送消息: " + message + " 到主题: " + topic); } } private void updateUIState() { runOnUiThread(() -> { if (isBound && mqttService != null) { boolean connected = mqttService.getMQTTManager().isConnected(); connectButton.setEnabled(!connected); disconnectButton.setEnabled(connected); subscribeButton.setEnabled(connected); unsubscribeButton.setEnabled(connected); sendButton.setEnabled(connected); } else { connectButton.setEnabled(false); disconnectButton.setEnabled(false); subscribeButton.setEnabled(false); unsubscribeButton.setEnabled(false); sendButton.setEnabled(false); } }); } private void appendLog(String message) { mainHandler.post(() -> { String timestamp = android.text.format.DateFormat.format("HH:mm:ss", System.currentTimeMillis()).toString(); String logEntry = "[" + timestamp + "] " + message + "\n"; logTextView.append(logEntry); // 自动滚动到底部 scrollView.fullScroll(View.FOCUS_DOWN); }); } private void showToast(String message) { mainHandler.post(() -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show()); } @Override public void onConnected() { appendLog("MQTT已连接"); updateUIState(); } @Override public void onDisconnected() { appendLog("MQTT已断开"); updateUIState(); } @Override public void onMessageReceived(String topic, String message) { appendLog("收到消息 - 主题: " + topic + ", 内容: " + message); } @Override public void onError(String error) { appendLog("错误: " + error); showToast(error); } @Override protected void onDestroy() { if (isBound) { unbindService(serviceConnection); isBound = false; } super.onDestroy(); } }

4. MQTTService.java

package cn.wx.mqtt; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class MQTTService extends Service { private static final String TAG = "MQTTService"; private final IBinder binder = new LocalBinder(); private MQTTManager mqttManager; public class LocalBinder extends Binder { public MQTTService getService() { return MQTTService.this; } } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "MQTT服务创建"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "MQTT服务启动"); return START_STICKY; // 服务被杀死后会自动重启 } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "MQTT服务绑定"); return binder; } @Override public boolean onUnbind(Intent intent) { Log.d(TAG, "MQTT服务解绑"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.d(TAG, "MQTT服务销毁"); if (mqttManager != null) { mqttManager.cleanup(); } super.onDestroy(); } public void initializeMQTT(String serverUri, String clientId, String username, String password) { if (mqttManager == null) { mqttManager = new MQTTManager(this, serverUri, clientId, username, password); } } public MQTTManager getMQTTManager() { return mqttManager; } }

5. MQTTManager.java

package cn.wx.mqtt; import android.content.Context; import android.util.Log; 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.MqttCallbackExtended; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class MQTTManager { private static final String TAG = "MQTTManager"; private MqttAndroidClient mqttAndroidClient; private String serverUri; private String clientId; private String username; private String password; private Context context; private MQTTCallback callback; private ScheduledExecutorService reconnectExecutor; private boolean isConnected = false; private boolean isConnecting = false; private int reconnectInterval = 5; // 重连间隔(秒) private int maxReconnectAttempts = 12*2; // 最大重连次数 暂定两分钟 private int reconnectAttempts = 0; public interface MQTTCallback { void onConnected(); void onDisconnected(); void onMessageReceived(String topic, String message); void onError(String error); } public MQTTManager(Context context, String serverUri, String clientId, String username, String password) { this.context = context; this.serverUri = serverUri; this.clientId = clientId; this.username = username; this.password = password; this.reconnectExecutor = Executors.newSingleThreadScheduledExecutor(); initClient(); } private void initClient() { try { mqttAndroidClient = new MqttAndroidClient(context, serverUri, clientId); mqttAndroidClient.setCallback(new MqttCallbackExtended() { @Override public void connectComplete(boolean reconnect, String serverURI) { Log.d(TAG, "连接完成: " + serverURI); isConnected = true; isConnecting = false; reconnectAttempts = 0; if (callback != null) { callback.onConnected(); } } @Override public void connectionLost(Throwable cause) { Log.e(TAG, "连接丢失", cause); isConnected = false; isConnecting = false; if (callback != null) { callback.onDisconnected(); } attemptReconnect(); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { String msg = new String(message.getPayload()); Log.d(TAG, "收到消息 - 主题: " + topic + ", 内容: " + msg); if (callback != null) { callback.onMessageReceived(topic, msg); } } @Override public void deliveryComplete(IMqttDeliveryToken token) { Log.d(TAG, "消息发送完成"); } }); } catch (Exception e) { Log.e(TAG, "初始化MQTT客户端失败", e); if (callback != null) { callback.onError("初始化MQTT客户端失败: " + e.getMessage()); } } } public void connect() { if (isConnected || isConnecting) { return; } isConnecting = true; try { MqttConnectOptions options = new MqttConnectOptions(); options.setAutomaticReconnect(false); // 我们自己处理重连 options.setCleanSession(true); options.setConnectionTimeout(10); options.setKeepAliveInterval(60); if (username != null && !username.isEmpty()) { options.setUserName(username); } if (password != null && !password.isEmpty()) { options.setPassword(password.toCharArray()); } IMqttToken token = mqttAndroidClient.connect(options); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.d(TAG, "MQTT连接成功"); isConnected = true; isConnecting = false; reconnectAttempts = 0; if (callback != null) { callback.onConnected(); } } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.e(TAG, "MQTT连接失败", exception); isConnected = false; isConnecting = false; if (callback != null) { callback.onError("连接失败: " + exception.getMessage()); } attemptReconnect(); } }); } catch (MqttException e) { Log.e(TAG, "连接MQTT服务器异常", e); isConnecting = false; if (callback != null) { callback.onError("连接异常: " + e.getMessage()); } attemptReconnect(); } } private void attemptReconnect() { if (reconnectAttempts < maxReconnectAttempts && !isConnected && !isConnecting) { reconnectAttempts++; Log.d(TAG, "尝试重连 (" + reconnectAttempts + "/" + maxReconnectAttempts + ")"); reconnectExecutor.schedule(() -> { if (!isConnected) { connect(); } }, reconnectInterval, TimeUnit.SECONDS); } else if (reconnectAttempts >= maxReconnectAttempts) { Log.e(TAG, "达到最大重连次数,停止重连"); if (callback != null) { callback.onError("达到最大重连次数,连接失败"); } } } public void subscribe(String topic, int qos) { if (!isConnected) { Log.w(TAG, "未连接到MQTT服务器,无法订阅主题"); return; } try { IMqttToken token = mqttAndroidClient.subscribe(topic, qos); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.d(TAG, "订阅主题成功: " + topic); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.e(TAG, "订阅主题失败: " + topic, exception); if (callback != null) { callback.onError("订阅主题失败: " + exception.getMessage()); } } }); } catch (MqttException e) { Log.e(TAG, "订阅主题异常: " + topic, e); if (callback != null) { callback.onError("订阅异常: " + e.getMessage()); } } } public void unsubscribe(String topic) { if (!isConnected) { Log.w(TAG, "未连接到MQTT服务器,无法取消订阅"); return; } try { IMqttToken token = mqttAndroidClient.unsubscribe(topic); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.d(TAG, "取消订阅主题成功: " + topic); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.e(TAG, "取消订阅主题失败: " + topic, exception); if (callback != null) { callback.onError("取消订阅失败: " + exception.getMessage()); } } }); } catch (MqttException e) { Log.e(TAG, "取消订阅主题异常: " + topic, e); if (callback != null) { callback.onError("取消订阅异常: " + e.getMessage()); } } } public void publish(String topic, String message, int qos, boolean retained) { if (!isConnected) { Log.w(TAG, "未连接到MQTT服务器,无法发送消息"); if (callback != null) { callback.onError("未连接到MQTT服务器,无法发送消息"); } return; } try { MqttMessage mqttMessage = new MqttMessage(); mqttMessage.setPayload(message.getBytes()); mqttMessage.setQos(qos); mqttMessage.setRetained(retained); IMqttToken token = mqttAndroidClient.publish(topic, mqttMessage); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.d(TAG, "消息发送成功 - 主题: " + topic + ", 内容: " + message); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.e(TAG, "消息发送失败", exception); if (callback != null) { callback.onError("消息发送失败: " + exception.getMessage()); } } }); } catch (MqttException e) { Log.e(TAG, "消息发送异常", e); if (callback != null) { callback.onError("消息发送异常: " + e.getMessage()); } } } public void disconnect() { try { if (mqttAndroidClient != null && mqttAndroidClient.isConnected()) { IMqttToken token = mqttAndroidClient.disconnect(); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.d(TAG, "MQTT断开连接成功"); isConnected = false; isConnecting = false; if (callback != null) { callback.onDisconnected(); } } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.e(TAG, "MQTT断开连接失败", exception); if (callback != null) { callback.onError("断开连接失败: " + exception.getMessage()); } } }); } } catch (MqttException e) { Log.e(TAG, "断开MQTT连接异常", e); if (callback != null) { callback.onError("断开连接异常: " + e.getMessage()); } } } public void setCallback(MQTTCallback callback) { this.callback = callback; } public boolean isConnected() { return isConnected; } public void setReconnectInterval(int seconds) { this.reconnectInterval = seconds; } public void setMaxReconnectAttempts(int attempts) { this.maxReconnectAttempts = attempts; } public void cleanup() { if (reconnectExecutor != null && !reconnectExecutor.isShutdown()) { reconnectExecutor.shutdown(); } disconnect(); } }

6. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Mqtttest"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MQTTService" android:enabled="true" android:exported="false" /> <service android:name="org.eclipse.paho.android.service.MqttService" /> </application> </manifest>

结束

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1206255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「LUCKY STUN穿透」使用邮件通知端口变化情况

「LUCKY STUN穿透」使用邮件通知端口变化情况「LUCKY STUN穿透」使用邮件通知端口变化情况 2024.05.21 在之前的一系列教程中我们介绍了一些STUN的用法 其中也包括了固定或更新端口的方法 但还有许多服务我们还不能实现…

「LUCKY STUN穿透」在Windows下使用VNT组网为非HTTP服务固定STUN穿透端口

「LUCKY STUN穿透」在Windows下使用VNT组网为非HTTP服务固定STUN穿透端口「LUCKY STUN穿透」在Windows下使用VNT组网为非HTTP服务固定STUN穿透端口 2024.10.23 索引文章结构 索引 │ ├─关于本教程 │ ├─已知的解决…

2026年 强磁磁铁厂家推荐排行榜,方块强磁、橡胶磁铁,工业级高吸附力磁体源头工厂精选

2026年强磁磁铁厂家推荐排行榜:聚焦方块强磁与橡胶磁铁的工业级高吸附力源头工厂 在工业制造、新能源、电子电器及自动化设备等领域,强磁磁铁(尤其是钕铁硼永磁体,俗称“强磁”)与橡胶磁铁作为核心功能材料,其性…

【Azure APIM】APIM的自建网关如何解决自签名证书的受信任问题呢?(方案三)

问题描述 在先前的四篇博文 1:【Azure APIM】APIM的自建网关如何解决自签名证书的受信任问题呢?(方案二) 2:【Azure APIM】APIM的自建网关如何解决自签名证书的受信任问题呢?(方案一) 3:【Azure APIM】如何解决…

AI大模型微调指南:告别“炼丹”玄学,用数据与科学打造专属模型

AI大模型微调指南:告别“炼丹”玄学,用数据与科学打造专属模型引言:为什么你需要掌握大模型微调? 在人工智能浪潮中,大型语言模型(LLM)如GPT、LLaMA、通义千问等已展现出惊人的通用能力。然而,你是否曾遇到这样…

安全加固相关内容

安全加固 核心原则为:最小权限原则以及纵深防御 指通过减少攻击面来提高系统安全性的过程。这是一个多层面的工作,通常遵循“纵深防御”(Defense in Depth)的原则,从底层系统到上层应用逐层进行。 以下是通用的安…

2026年优质建筑材料检测服务商推荐与机构选择指南

在建筑材料检测的过程中,有效的内容概要不仅帮助读者快速了解文章脉络,也方便他们掌握核心信息。本篇文章围绕建筑材料检测服务的重要性,提供了对检测机构选择的实用建议。此外,我们将探讨值得信赖的检测服务商,分…

Product Hunt 每日热榜 | 2026-01-23

1. ChartGen AI 标语&#xff1a;几秒钟内将数据转化为专业的图表&#xff0c;获取深刻见解。 介绍&#xff1a;来自Ada.im团队的ChartGen AI是一款智能图表生成器&#xff0c;它可以将原始数据转化为节省成本的洞察。这个工具特别帮助在线营销人员将来自不同平台的数据&…

FPGA教程系列-Vivado Aurora 8B/10B IP核接口解析 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

TB132FU原厂刷机包免费下载_CN_ZUI_16

原厂刷机包下载 https://pan.quark.cn/s/7bcaee17dad9联想平板小新Pad Pro 2022 11.2英寸 平板电脑原厂刷机包下载 转载请标注来源:https://www.cnblogs.com/mianfeijiaocheng/p/19523822 所有固件都是我手动上传的,…

2026年磁铁厂家推荐排行榜:铁氧体/钕铁硼/无线充/耐高温/单面/瓦形/沉头孔/方形/圆形/异形/圆环磁铁,源头实力与创新应用深度解析

2026年磁铁厂家推荐排行榜:铁氧体/钕铁硼/无线充/耐高温/单面/瓦形/沉头孔/方形/圆形/异形/圆环磁铁,源头实力与创新应用深度解析 磁性材料作为现代工业的“隐形骨骼”,其性能与品质直接关系到下游终端产品的可靠性…

如何进行员工绩效评估

帕特里夏金(Patricia King)在她的《绩效计划与评估》一书中指出,法律要求绩效评估必须:与工作相关且有效;基于对工作的透彻分析;为所有员工标准化;不偏against任何种族,肤色,性别,宗教或国籍;并由对该人或工…

区块链去中心化存储的Prompt工程:提示工程架构师的数据管理

区块链去中心化存储与Prompt工程协同&#xff1a;提示架构师的数据管理实践指南 一、引言&#xff1a;当Prompt工程遇到数据存储的“阿喀琉斯之踵” 假设你是一位资深的Prompt工程架构师&#xff0c;正在为某大型AI模型设计用户意图理解的提示策略。为了让Prompt更精准&#…

Ubuntu 上搜狗输入法突然“消失 / 只能英文”的排查与修复教程

Ubuntu 上搜狗输入法突然“消失 / 只能英文”的排查与修复教程 适用场景&#xff1a;Ubuntu 桌面系统里原本装了搜狗输入法&#xff08;Sogou Pinyin&#xff09;&#xff0c;突然只能输入英文&#xff1b;找不到切换快捷键&#xff1b;输入法图标不见或无法切换到中文。 典型原…

亲测好用10个AI论文平台,助你轻松搞定本科生毕业论文!

亲测好用10个AI论文平台&#xff0c;助你轻松搞定本科生毕业论文&#xff01; AI 工具助力论文写作&#xff0c;轻松应对学术挑战 在当前的学术环境中&#xff0c;越来越多的学生开始借助 AI 工具来提升论文写作效率。无论是降低 AIGC 率&#xff0c;还是保持语义通顺&#xff…

2026研究生必备10个降AI率工具

2026研究生必备10个降AI率工具 AI降重工具&#xff1a;让论文更“自然”的秘密武器 随着人工智能技术的广泛应用&#xff0c;越来越多的研究生在撰写论文时不得不面对一个现实问题——AIGC率过高。这不仅影响论文的原创性评估&#xff0c;还可能对最终成绩产生负面影响。而AI降…

深入解析:【要闻周报】网络安全与数据合规 11-21

深入解析:【要闻周报】网络安全与数据合规 11-21pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas",…

2026年 印刷机厂家推荐排行榜:丝网印刷机/线路板印刷机/全自动印刷机/CCD全自动印刷机/亚克力印刷机/大尺寸印刷机,高精度与高效能智造之选

2026年印刷机厂家推荐排行榜:丝网印刷机/线路板印刷机/全自动印刷机/CCD全自动印刷机/亚克力印刷机/大尺寸印刷机,高精度与高效能智造之选 在全球制造业持续向智能化、精密化转型的浪潮下,印刷设备作为电子制造、光…

Spark机器学习库MLlib:大数据AI应用开发指南

Spark机器学习库MLlib:大数据AI应用开发指南 1. 引入与连接 1.1 引人入胜的开场 想象一下,你身处一家大型电商公司,每天都有海量的用户行为数据涌入,包括用户的浏览记录、购买历史、搜索关键词等。公司想要精准地预测用户的购买倾向,以便推送个性化的商品推荐,从而提高…

深度测评自考必备AI论文平台TOP10

深度测评自考必备AI论文平台TOP10 自考论文写作工具测评&#xff1a;2026年TOP10榜单出炉 随着自考人数逐年攀升&#xff0c;论文写作成为众多考生面临的共同难题。从选题构思到文献检索&#xff0c;再到格式规范与查重修改&#xff0c;每一步都可能成为“卡壳点”。为帮助自考…