Kotlin开发Android应用连接HiveMQ时whenComplete未执行求助
问题描述
用Kotlin开发Android应用,通过HiveMQ发布消息给ESP8266,参考官方文档适配代码后,调试日志始终不打印,推测whenComplete回调从未执行。代码如下:
val builder = MqttClient.builder() .identifier(UUID.randomUUID().toString()) .serverHost("server.hivemq.cloud") .serverPort(8883) .sslWithDefaultConfig(); val client = builder.useMqttVersion5().buildAsync(); client.connectWith() .simpleAuth() .username("username") .password("password".toByteArray()) .applySimpleAuth() .send() .whenComplete { connAck, throwable -> run { Log.d("TAG", "Some debug string"); if (throwable != null) { Toast.makeText( context, "Unable to connect to HiveMQ servers!!", Toast.LENGTH_LONG ).show(); } else { client.publishWith() .topic("my/topic") .payload("ChopChop".toByteArray()) .send() .whenComplete { publish, throwable -> run { if(throwable != null) { Toast.makeText(context, "Unable to publish message!", Toast.LENGTH_LONG).show(); } client.disconnect(); } } } } }
排查线索
检查网络权限:确保
AndroidManifest.xml中添加互联网权限:<uses-permission android:name="android.permission.INTERNET" />Android 9及以上默认禁止明文流量,但HiveMQ Cloud用8883端口(SSL加密),无需额外配置
usesCleartextTraffic,但权限必须存在。线程问题:
whenComplete回调默认在后台线程执行,直接调用Toast.makeText会触发主线程异常,导致回调执行中断且无日志。需将UI操作切换到主线程,比如用Handler(Looper.getMainLooper()).post{ ... }包裹Toast代码。添加异常捕获:在
send()后追加exceptionally方法,捕获请求发送阶段的异常(比如网络连接失败、参数错误),避免异常被直接吞掉:.send() .exceptionally { throwable -> Log.e("TAG", "Request failed", throwable) null }检查Logcat配置:确认Logcat的TAG过滤正确,没有隐藏Debug级别日志,且选择了当前应用进程。
SSL证书验证:设备时间不正确会导致SSL证书验证失败,检查设备系统时间是否同步。若仍有问题,可尝试自定义SSL配置(比如信任HiveMQ的证书)。
客户端生命周期:
client是局部变量,可能在回调执行前被GC回收,将其改为类成员变量,延长生命周期。
修正后的代码示例
import android.os.Handler import android.os.Looper import android.widget.Toast import org.eclipse.paho.mqttv5.client.MqttClient import java.util.UUID // 将client设为类成员变量,避免被提前回收 private lateinit var client: MqttClient fun connectAndPublish(context: Context) { val builder = MqttClient.builder() .identifier(UUID.randomUUID().toString()) .serverHost("server.hivemq.cloud") .serverPort(8883) .sslWithDefaultConfig() client = builder.useMqttVersion5().buildAsync() client.connectWith() .simpleAuth() .username("username") .password("password".toByteArray()) .applySimpleAuth() .send() .exceptionally { throwable -> Log.e("TAG", "Connect request failed", throwable) Handler(Looper.getMainLooper()).post { Toast.makeText(context, "Connect request failed!", Toast.LENGTH_LONG).show() } null } .whenComplete { connAck, throwable -> Log.d("TAG", "Connect callback triggered") Handler(Looper.getMainLooper()).post { if (throwable != null) { Log.e("TAG", "Connect failed", throwable) Toast.makeText( context, "Unable to connect to HiveMQ servers!!", Toast.LENGTH_LONG ).show() } else { Log.d("TAG", "Connected successfully") client.publishWith() .topic("my/topic") .payload("ChopChop".toByteArray()) .send() .exceptionally { publishThrowable -> Log.e("TAG", "Publish request failed", publishThrowable) Handler(Looper.getMainLooper()).post { Toast.makeText(context, "Publish request failed!", Toast.LENGTH_LONG).show() } null } .whenComplete { publish, publishThrowable -> Handler(Looper.getMainLooper()).post { if (publishThrowable != null) { Log.e("TAG", "Publish failed", publishThrowable) Toast.makeText(context, "Unable to publish message!", Toast.LENGTH_LONG).show() } client.disconnect() } } } } } }
内容的提问来源于stack exchange,提问作者Gaurav Joseph
相关产品推荐
相关产品推荐

