Пытался отправить сообщение платформы во Flutter, но FlutterJNI был отключен от собственного C ++ после закрытия приложения - PullRequest
0 голосов
/ 21 июня 2020

Я использую pahoo mqtt на стороне android и реализую его на флаттере, чтобы он запускался, когда приложение было закрыто. Однако клиент все еще подключен и все еще получает сообщение от брокера после того, как я закрываю приложение. Но когда я снова открываю приложение, кажется, что он не смог вызвать метод со стороны 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.

Я также получил эту ошибку после того, как закрыл app

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()
        }
    }
}

может кто-нибудь решить эту проблему ,,, извините за плохой англи sh

...