我在 android 端使用 pahoo mqtt 并在 Flutter 上实现它以使其在应用程序关闭时运行。但是,客户端仍然连接,并且在我关闭应用程序后仍然从经纪人那里收到消息。但是,当我再次打开应用程序时,似乎无法在消息到达时从 android 端调用方法mBackgroundChannel.invokeMethod("mqttMessageArrive", strMessage)
并收到此警告消息Tried to send a platform message to Flutter, but FlutterJNI was detached from native C++. Could not send. Channel: com.example.research_cahyo/method_dart. Response ID: 0
。
关闭应用程序后我也收到此错误
2020-06-18 17:27:16.751 27939-27939/com.example.research_cahyo E/ActivityThread: Activity com.example.research_cahyo.MainActivity has leaked ServiceConnection org.eclipse.paho.android.service.MqttAndroidClient$MyServiceConnection@4c11377 that was originally bound here
android.app.ServiceConnectionLeaked: Activity com.example.research_cahyo.MainActivity has leaked ServiceConnection org.eclipse.paho.android.service.MqttAndroidClient$MyServiceConnection@4c11377 that was originally bound here
at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1813)
at android.app.LoadedApk.getServiceDispatcherCommon(LoadedApk.java:1685)
at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:1664)
at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1732)
at android.app.ContextImpl.bindService(ContextImpl.java:1661)
at android.content.ContextWrapper.bindService(ContextWrapper.java:715)
at org.eclipse.paho.android.service.MqttAndroidClient.connect(MqttAndroidClient.java:425)
at com.example.research_cahyo.mqtt.MQTTConnection.doConnect(MqttConnection.kt:32)
at com.example.research_cahyo.MyPlugin.doStartMqttService(MyPlugin.kt:69)
at com.example.research_cahyo.MyPlugin.onMethodCall(MyPlugin.kt:149)
at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:231)
at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:93)
at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:642)
下面是我的 mainactivity.kt
class MainActivity : FlutterActivity() {
private val TAG = "MAIN ACTIVITY";
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(Intent(activity.applicationContext, NotificationService::class.java))
} else {
startService(Intent(activity.applicationContext, NotificationService::class.java))
}
GeneratedPluginRegistrant.registerWith(flutterEngine);
Storage.initValue(this.applicationContext)
val binaryMessenger = flutterEngine.getDartExecutor().getBinaryMessenger()
MethodChannel(binaryMessenger, INVOKE_METHOD_ANDROID)
.setMethodCallHandler(MyPlugin(this, binaryMessenger))
}
}
这是 myplugin.kt
class MyPlugin(private val activity: Activity, binaryMessenger: BinaryMessenger) : MethodChannel.MethodCallHandler, IMqttCallback {
private var mBackgroundChannel: MethodChannel
private lateinit var subscribeTopic: String
init {
mBackgroundChannel = MethodChannel(binaryMessenger, INVOKE_METHOD_DART)
}
fun onPublishMessage(call: MethodCall, rawResult: MethodChannel.Result) {
val params = call.arguments<Map<String, String>>()
if (params.containsKey("messages") && params.containsKey("topic")) {
val messages = params["messages"] ?: ""
val topic = params["topic"] ?: ""
MQTTConnection.instance?.doPublishMessages(messages, topic)
rawResult.success(true)
} else {
rawResult.error("INCOMPLETE ARGS", "ARGUMEN ARE INCOMPLETE", null);
}
}
fun doCheckMqttStatus(result: MethodChannel.Result) {
result.success(MQTTConnection.instance?.isConnected)
}
fun doUnSubscribeTopic(call: MethodCall, result: MethodChannel.Result) {
val param: Map<String, String> = call.arguments();
val topic: String = param.get("topic") ?: ""
if (topic.isNotEmpty()) {
MQTTConnection.instance?.doUnSubscribeTopic(topic, this)
}
}
fun doStartMqttService(call: MethodCall, result: MethodChannel.Result) {
val param: Map<String, String> = call.arguments();
val serverUri: String = param.get("serverUri") ?: ""
val clientId: String = param.get("clientId") ?: ""
val clientUsername: String = param.get("clientUsername") ?: ""
val clientPassword: String = param.get("clientPassword") ?: ""
subscribeTopic = param.get("subscribeTopic") ?: ""
val valid = serverUri.length > 0 && clientId.length > 0 &&
clientUsername.length > 0 && clientPassword.length > 0 &&
subscribeTopic.length > 0
if (valid) {
Storage.saveValue(MQTTOPTIONS_STORAGE_KEY, "$serverUri,$clientId,$clientUsername,$clientPassword,$subscribeTopic")
}
if (valid && !(MQTTConnection.instance?.isConnected ?: false)) {
MQTTConnection.instance?.doConnect(activity, serverUri, clientId, clientUsername, clientPassword, this)
result.success("Start mqtt invoked")
} else {
result.error("Invalid Arguments", "Mqtt failed to invoked", null)
}
}
fun doStopMqttService(result: MethodChannel.Result) {
MQTTConnection.instance?.doDisConnect(true)
result.success("Stop mqtt invoked")
}
fun onGetNotifications(result: MethodChannel.Result) {
val listMessage = (Storage.getValue(NOTIFICATION_STORAGE_KEY) as List<*>).map { it.toString() }
result.success(listMessage)
}
fun onSetNotification(call: MethodCall, result: MethodChannel.Result) {
try {
val params = (call.arguments() as List<*>).map { it.toString() };
Storage.saveValue(NOTIFICATION_STORAGE_KEY, params)
} catch (e: Exception) {
result.error("Set storage error", "Set Notification Error", null);
}
}
override fun onMQTTConnectionSuccess() {
if (!(MQTTConnection.instance?.hasTopic(subscribeTopic) ?: false)) {
MQTTConnection.instance?.doSubscribeTopic(subscribeTopic, this)
}
}
override fun onMQTTSubscribeTopicSuccess() {
MQTTConnection.instance?.doMessageListen(this)
}
override fun onMQTTSubscribeTopicFailed(messages: String?) {
mBackgroundChannel.invokeMethod("mqttSubscribeFailed", messages)
}
override fun onMQTTConnectionFailed(messages: String?) {
mBackgroundChannel.invokeMethod("mqttConnectFailed", messages)
}
override fun onMQTTMessagesArrived(mqttMessage: MqttMessage?) {
mqttMessage?.let {
val strMessage = String(it.payload)
mBackgroundChannel.invokeMethod("mqttMessageArrive", strMessage)
val listMessage = (Storage.getValue(NOTIFICATION_STORAGE_KEY) as MutableList<*>).map {
it.toString()
}.toMutableList()
listMessage.add(strMessage)
Storage.saveValue(NOTIFICATION_STORAGE_KEY, listMessage)
Log.d(TAG, "message has arrived")
val notificationBuilder = NotificationCompat.Builder(activity.applicationContext, Constant.CHANNEL_ID)
notificationBuilder.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Message")
.setContentText(strMessage)
.setVibrate(arrayListOf(1000L, 1000L, 1000L, 1000L).toLongArray())
val notification = notificationBuilder.build()
with(NotificationManagerCompat.from(activity.applicationContext)) {
this.notify(Random.nextInt(0, 100), notification)
}
}
}
override fun onMQTTUnsubscribeSuccess() {
mBackgroundChannel.invokeMethod("mqttUnsubscribeSuccess", "Mqtt unsubscribe success")
}
override fun onMQTTUnsubscribeFailed() {
mBackgroundChannel.invokeMethod("mqttUnsubscribeFailed", "Mqtt unsubscribe failed")
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"publishMessage" -> onPublishMessage(call, result)
"startMqttService" -> doStartMqttService(call, result)
"stopMqttService" -> doStopMqttService(result)
"checkMqttStatus" -> doCheckMqttStatus(result)
"unsubscribeTopic" -> doUnSubscribeTopic(call, result)
"getNotification" -> onGetNotifications(result)
"setNotification" -> onSetNotification(call, result)
else -> result.notImplemented()
}
}
}
谁能解决这个问题,抱歉英语不好