3

I have been trying to implement mqtt using hivemq in my Android app. Though I have used the same specs and configuration from their docs, I am still unable to establish a successful connection.

I was able to use paho for mqtt earlier, but it doesn't work for android Oreo and above if the app is in background because the library didn't have startServiceForeground update. So moved to HiveMq. I am just trying their sample app using the quick start guides here. 1. https://hivemq.github.io/hivemq-mqtt-client/ 2. https://www.hivemq.com/blog/mqtt-client-library-enyclopedia-hivemq-mqtt-client/ 3. https://github.com/hivemq/hivemq-mqtt-client/blob/develop/README.md Almost wasted a day to figure how to connect to their mqtt, but unsuccessful

lateinit var client : Mqtt3Client

    fun connect() {
        client = Mqtt3Client.builder()
             .identifier(UUID.randomUUID().toString())
            .serverHost("broker.hivemq.com")
            .serverPort(1883)
            .buildAsync()


            client.toAsync().connect()
            .whenComplete { mqtt3ConnAck, throwable ->
                if (throwable != null) {
                    // handle failure
                    android.util.Log.v("HIVE-MQTT-LCDP", " connection failed")
                } else {
                    android.util.Log.v("HIVE-MQTT-LCDP", " connected")
                    // setup subscribes or start publishing
                    subscribe()
                    publish()
                }
            }

        fab.setOnLongClickListener {
            android.util.Log.v("HIVE-MQTT-LCDP", " disconnected")
            client.toAsync().disconnect()
            true
        }

    }


    fun publish() {
        client.toAsync().publishWith()
            .topic("the/topic")
            .payload("payload".toByteArray())
            .send()
            .whenComplete { mqtt3Publish, throwable ->
                if (throwable != null) {
                    android.util.Log.v("HIVE-MQTT-LCDP", " failure to publish")
                    // handle failure to publish
                } else {
                    android.util.Log.v("HIVE-MQTT-LCDP", " successful to publish")
                    // handle successful publish, e.g. logging or incrementing a metric
                }
            }
    }

    fun subscribe() {
        client.toAsync().subscribeWith()
            .topicFilter("the/topic")
            .callback { mqtt3Publish ->
                // Process the received message
                android.util.Log.v("HIVE-MQTT-LCDP", " Message received")
            }
            .send()
            .whenComplete { mqtt3SubAck, throwable ->
                if (throwable != null) {
                    android.util.Log.v("HIVE-MQTT-LCDP", " failure to subscribe")
                    // Handle failure to subscribe
                } else {
                    android.util.Log.v("HIVE-MQTT-LCDP", " successful to subscribe")
                    // Handle successful subscription, e.g. logging or incrementing a metric
                }
            }
    }```

expecting a response in the subscribe-whenComplete.

the clues:

it throws the exception "com.hivemq.client.mqtt.exceptions.ConnectionClosedException: Server closed connection without DISCONNECT." in the addConnectionListener

Stacktrace:

   Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.logging.log4j.spi.ExtendedLoggerWrapper" on path: DexPathList[[zip file "/data/app/com.example.myapplication-jscQ0Rz9LiCQTlaR1v-Z5w==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.myapplication-jscQ0Rz9LiCQTlaR1v-Z5w==/lib/arm64, /system/lib64, /system/vendor/lib64]]
        at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:93)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
        at io.netty.util.internal.logging.InternalLogger io.netty.util.internal.logging.Log4J2LoggerFactory.newInstance(java.lang.String) (Log4J2LoggerFactory.java:33)
        at io.netty.util.internal.logging.InternalLoggerFactory io.netty.util.internal.logging.InternalLoggerFactory.newDefaultFactory(java.lang.String) (InternalLoggerFactory.java:51)
        at io.netty.util.internal.logging.InternalLoggerFactory io.netty.util.internal.logging.InternalLoggerFactory.getDefaultFactory() (InternalLoggerFactory.java:67)
        at io.netty.util.internal.logging.InternalLogger io.netty.util.internal.logging.InternalLoggerFactory.getInstance(java.lang.String) (InternalLoggerFactory.java:93)
        at io.netty.util.internal.logging.InternalLogger io.netty.util.internal.logging.InternalLoggerFactory.getInstance(java.lang.Class) (InternalLoggerFactory.java:86)
        at void io.netty.util.internal.SystemPropertyUtil.<clinit>() (SystemPropertyUtil.java:29)
        at boolean io.netty.util.internal.SystemPropertyUtil.getBoolean(java.lang.String, boolean) (SystemPropertyUtil.java:99)
        at void io.netty.channel.epoll.Epoll.<clinit>() (Epoll.java:31)
        at boolean io.netty.channel.epoll.Epoll.isAvailable() (Epoll.java:68)
        at com.hivemq.client.internal.mqtt.netty.NettyEventLoopProvider com.hivemq.client.internal.mqtt.netty.NettyModule.provideNettyEventLoopProvider() (NettyModule.java:40)
        at com.hivemq.client.internal.mqtt.netty.NettyEventLoopProvider com.hivemq.client.internal.mqtt.netty.NettyModule_ProvideNettyEventLoopProviderFactory.proxyProvideNettyEventLoopProvider() (NettyModule_ProvideNettyEventLoopProviderFactory.java:31)
        at com.hivemq.client.internal.mqtt.netty.NettyEventLoopProvider com.hivemq.client.internal.mqtt.netty.NettyModule_ProvideNettyEventLoopProviderFactory.provideInstance() (NettyModule_ProvideNettyEventLoopProviderFactory.java:22)
        at com.hivemq.client.internal.mqtt.netty.NettyEventLoopProvider com.hivemq.client.internal.mqtt.netty.NettyModule_ProvideNettyEventLoopProviderFactory.get() (NettyModule_ProvideNettyEventLoopProviderFactory.java:18)
        at java.lang.Object com.hivemq.client.internal.mqtt.netty.NettyModule_ProvideNettyEventLoopProviderFactory.get() (NettyModule_ProvideNettyEventLoopProviderFactory.java:7)
        at java.lang.Object dagger.internal.DoubleCheck.get() (DoubleCheck.java:47)
        at com.hivemq.client.internal.mqtt.netty.NettyEventLoopProvider com.hivemq.client.internal.mqtt.ioc.DaggerSingletonComponent.nettyEventLoopProvider() (DaggerSingletonComponent.java:377)
        at io.netty.channel.EventLoop com.hivemq.client.internal.mqtt.MqttClientConfig.acquireEventLoop() (MqttClientConfig.java:174)
        at void com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckSingle.subscribeActual(io.reactivex.SingleObserver) (MqttConnAckSingle.java:69)
        at void io.reactivex.Single.subscribe(io.reactivex.SingleObserver) (Single.java:3575)
        at void io.reactivex.internal.operators.single.SingleObserveOn.subscribeActual(io.reactivex.SingleObserver) (SingleObserveOn.java:35)
        at void io.reactivex.Single.subscribe(io.reactivex.SingleObserver) (Single.java:3575)
        at void com.hivemq.client.internal.rx.RxFutureConverter$RxJavaSingleFuture.<init>(io.reactivex.Single) (RxFutureConverter.java:114)
I/zygote64:     at java.util.concurrent.CompletableFuture com.hivemq.client.internal.rx.RxFutureConverter.toFuture(io.reactivex.Single) (RxFutureConverter.java:44)
        at java.util.concurrent.CompletableFuture com.hivemq.client.internal.mqtt.MqttAsyncClient.connect(com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect) (MqttAsyncClient.java:70)
        at java.util.concurrent.CompletableFuture com.hivemq.client.internal.mqtt.mqtt3.Mqtt3AsyncClientView.connect(com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect) (Mqtt3AsyncClientView.java:116)
        at java.util.concurrent.CompletableFuture com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient.connect() (Mqtt3AsyncClient.java:59)
        at void com.example.myapplication.MainActivity.connect() (MainActivity.kt:70)
        at void com.example.myapplication.MainActivity.onCreate(android.os.Bundle) (MainActivity.kt:58)
        at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:7183)
        at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1220)
        at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2910)
        at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:3032)
        at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
        at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1696)
        at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
        at void android.os.Looper.loop() (Looper.java:164)
        at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6944)
        at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
        at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:327)
        at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:1374)
E/zygote64: No implementation found for int io.netty.channel.epoll.Native.offsetofEpollData() (tried Java_io_netty_channel_epoll_Native_offsetofEpollData and Java_io_netty_channel_epoll_Native_offsetofEpollData__)
I/PlatformDependent: Your platform does not provide complete low-level API for accessing direct buffers reliably. Unless explicitly requested, heap buffer will always be preferred to avoid potential system instability.
W/io.netty.util.NetUtil: Failed to find the loopback interface
W/MacAddressUtil: Failed to find a usable hardware address from the network interfaces; using random bytes: 20:c2:d8:6a:3f:bc:f6:90
W/DefaultPromise: An exception was thrown by com.hivemq.client.internal.mqtt.handler.connect.-$$Lambda$MqttConnAckSingle$1NP8pOpp3tvaWFx_4_jMw-CQFiU.operationComplete()
    java.lang.IllegalStateException: MqttClientReconnector must be called from the eventLoop.
        at com.hivemq.client.internal.mqtt.lifecycle.MqttClientReconnector.checkThread(MqttClientReconnector.java:158)
        at com.hivemq.client.internal.mqtt.lifecycle.MqttClientReconnector.isReconnect(MqttClientReconnector.java:93)
        at com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckSingle.reconnect(MqttConnAckSingle.java:135)
        at com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckSingle.reconnect(MqttConnAckSingle.java:103)
        at com.hivemq.client.internal.mqtt.handler.connect.MqttConnAckSingle.lambda$connect$0(MqttConnAckSingle.java:90)
        at com.hivemq.client.internal.mqtt.handler.connect.-$$Lambda$MqttConnAckSingle$1NP8pOpp3tvaWFx_4_jMw-CQFiU.operationComplete(Unknown Source:8)
        at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511)
        at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:485)
        at io.netty.util.concurrent.DefaultPromise.access$000(DefaultPromise.java:33)
        at io.netty.util.concurrent.DefaultPromise$1.run(DefaultPromise.java:435)
        at io.netty.util.concurrent.GlobalEventExecutor$TaskRunner.run(GlobalEventExecutor.java:248)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.lang.Thread.run(Thread.java:764)
D/OpenGLRenderer: HWUI GL Pipeline
D/ViewRootImpl@2daeee6[MainActivity]: setView = DecorView@cea6ed4[MainActivity] TM=true MM=false
V/InputMethodManager: Not IME target window, ignoring
D/ViewRootImpl@2daeee6[MainActivity]: dispatchAttachedToWindow
V/Surface: sf_framedrop debug : 0x4f4c, game : false, logging : 0
D/ViewRootImpl@2daeee6[MainActivity]: Relayout returned: old=[0,0][0,0] new=[0,0][1080,1920] result=0x7 surface={valid=true 481715916800} changed=true
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 2
D/libGLESv1: STS_GLApi : DTS, ODTC are not allowed for Package : com.example.myapplication
D/mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, egl_color_buffer_format *, EGLBoolean) returns 0x3000,  [1080x1920]-format:1
D/OpenGLRenderer: eglCreateWindowSurface = 0x702882f2b0
E/System: Uncaught exception thrown by finalizer
E/System: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.io.FileDescriptor.isSocket$()' on a null object reference
        at sun.nio.ch.FileDispatcherImpl.preCloseImpl(FileDispatcherImpl.java:115)
        at sun.nio.ch.SocketDispatcher.preClose(SocketDispatcher.java:66)
        at sun.nio.ch.SocketChannelImpl.implCloseSelectableChannel(SocketChannelImpl.java:883)
        at java.nio.channels.spi.AbstractSelectableChannel.implCloseChannel(AbstractSelectableChannel.java:234)
        at java.nio.channels.spi.AbstractInterruptibleChannel.close(AbstractInterruptibleChannel.java:116)
        at sun.nio.ch.SocketChannelImpl.finalize(SocketChannelImpl.java:937)
        at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250)
        at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237)
        at java.lang.Daemons$Daemon.run(Daemons.java:103)
        at java.lang.Thread.run(Thread.java:764)
I/zygote64: Do partial code cache collection, code=61KB, data=53KB
I/zygote64: After code cache collection, code=61KB, data=53KB
    Increasing code cache capacity to 256KB
D/ViewRootImpl@2daeee6[MainActivity]: Relayout returned: old=[0,0][1080,1920] new=[0,0][1080,1920] result=0x3 surface={valid=true 481715916800} changed=false
I/zygote64: Compiler allocated 9MB to compile void android.widget.TextView.<init>(android.content.Context, android.util.AttributeSet, int, int)
D/ViewRootImpl@2daeee6[MainActivity]: MSG_RESIZED_REPORT: frame=Rect(0, 0 - 1080, 1920) ci=Rect(0, 72 - 0, 0) vi=Rect(0, 72 - 0, 0) or=1
D/ViewRootImpl@2daeee6[MainActivity]: MSG_WINDOW_FOCUS_CHANGED 1
V/InputMethodManager: Starting input: tba=android.view.inputmethod.EditorInfo@159ea78 nm : com.example.myapplication ic=null
I/InputMethodManager: startInputInner - mService.startInputOrWindowGainedFocus
V/InputMethodManager: Starting input: tba=android.view.inputmethod.EditorInfo@9899551 nm : com.example.myapplication ic=null
D/ViewRootImpl@2daeee6[MainActivity]: ViewPostIme pointer 0
D/ViewRootImpl@2daeee6[MainActivity]: ViewPostIme pointer 1
V/HIVE-MQTT-LCDP:  failure to publish
I/zygote64: Do full code cache collection, code=123KB, data=95KB
I/zygote64: After code cache collection, code=102KB, data=64KB
satya phani
  • 45
  • 1
  • 6

2 Answers2

5

You have to add the following permission to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>

(see https://github.com/hivemq/hivemq-mqtt-client/issues/213)

The ClassNotFoundException is just a log message and not an error. Netty (the network library used by the HiveMQ MQTT Client) tries to detect if you have a logging framework loaded. So adding a logging framework is optional.


Update for Proguard:

Netty and JCTools can not be proguarded well, so add these proguard rules:

-keepclassmembernames class io.netty.** {
    *;
}

-keepclassmembernames class org.jctools.** {
    *;
}
SgtSilvio
  • 476
  • 2
  • 5
  • Hey Silvio, Yeah I was able to figure that it needs internet permission in Manifest. Now when I run, I am getting this error in run time exactly at "mqttClient!!.connect()". do you have any clue?? E/art: No implementation found for int io.netty.channel.epoll.Native.offsetofEpollData() (tried Java_io_netty_channel_epoll_Native_offsetofEpollData and Java_io_netty_channel_epoll_Native_offsetofEpollData__) E/UncaughtException: java.lang.ExceptionInInitializerError – satya phani Jun 21 '19 at 20:41
  • Here is a more detail error `E/art: No implementation found for int io.netty.channel.epoll.Native.offsetofEpollData() (tried Java_io_netty_channel_epoll_Native_offsetofEpollData and Java_io_netty_channel_epoll_Native_offsetofEpollData__) I/io.netty.util.b.z: Your platform does not provide complete low-level API for accessing direct buffers reliably. Unless explicitly requested, heap buffer will always be preferred to avoid potential system instability. D/AndroidRuntime: Shutting down VM E/UncaughtException: java.lang.ExceptionInInitializerError` – satya phani Jun 21 '19 at 20:49
  • If I set the minifyEnabled, shrinkResources to false in gradle, everything is working as Intended. Perfect! but if I set them to true ( I must before I deploy to store) it is throwing this error. `E/art: No implementation found for int io.netty.channel.epoll.Native.offsetofEpollData()` – satya phani Jun 21 '19 at 22:13
  • 1
    `No implementation found for int io.netty.channel.epoll.Native.offsetofEpollData()` and `Your platform does not provide complete low-level API for accessing direct buffers reliably. Unless explicitly requested, heap buffer will always be preferred to avoid potential system instability.` are just logs caused by Netty. They should not affect the operation of your app. Can you post the stack trace of the ExceptionInInitializerError? – SgtSilvio Jun 23 '19 at 10:00
  • 1
    I updated the answer to address issues with proguard – SgtSilvio Jun 23 '19 at 16:04
  • Hi @SgtSilvio, thank you for looking into this issue. I have added the proguard rules and it worked fine and didn't throw any errors in my S7 that runs on Oreo. Tried to run on S4 with lollipop as my app supports OS versions till lollipop and found a different issue. ```E/UncaughtException: java.lang.NoClassDefFoundError: com.hivemq.client.internal.mqtt.mqtt3.-$$Lambda$Mqtt3AsyncClientView$cgIqCOTrA3i2B3XLk_wChmlct74```. Looks like another proguard issue. Tried to add ```-keep class com.hivemq.client.internal.mqtt.** { *; }``` but didn't work. I would be glad to use your help here. Thank you – satya phani Jun 24 '19 at 03:08
  • it is just not logs but crashing the app. To be specific crashing exactly at **buildAsync()** call (some clue: crashing on S4 with lollipop and no crashes on S7 with Oreo) **error** ```java.lang.NoClassDefFoundError: com.hivemq.client.internal.mqtt.mqtt3.-$$Lambda$Mqtt3AsyncClientView$cgIqCOTrA3i2B3XLk_wChmlct74``` ```mqttClient = Mqtt3Client.builder() .identifier(clientId) .serverHost(settings.brokerHost) .serverPort(settings.brokerPort) .sslWithDefaultConfig() .addConnectedListener(HiveMqttConnection) .addDisconnectedListener(HiveMqttConnection) .buildAsync()``` – satya phani Jun 24 '19 at 03:34
  • As this is a different question (regarding Android API level compatibility) I think you should open a new question for it. If the answer solved your initial issue please mark it as resolved. – SgtSilvio Jun 24 '19 at 07:04
  • @satya phani: Regarding your question about lower Android versions, the gradle plugin "Android RetroFix" (https://github.com/SgtSilvio/android-retrofix) is needed to use the HiveMQ MQTT client library on Android APIs < 24 – SgtSilvio Jul 14 '19 at 21:26
  • Hey SgtSilvio, Thank you a tonne for helping me with this issue. I have blocked my app not to use hiveMQ for versions < 24 for now. But other api versions working pretty good with hiveMQ. I will apply the "Android RetroFix" in the very next release and let you know the status. I had marked your answer as Resolved too. – satya phani Jul 15 '19 at 20:40
  • I got new issue when I use the lib in debug mode it work good but when I use release mode with proguard file that @SgtSilvio mentioned, I get below crashes, can anyone help me? : – hkh114 Mar 12 '20 at 21:01
  • Exception: java.lang.NoClassDefFoundError: p.a.a.h at com.hivemq.client.internal.mqtt.handler.publish.outgoing.MqttOutgoingQosHandler.(MqttOutgoingQosHandler.java:3).. and this one: Caused by java.lang.ExceptionInInitializerError – hkh114 Mar 12 '20 at 21:02
2

Try adding this in you build file

https://mvnrepository.com/artifact/log4j/log4j/1.2.17

compile group: 'log4j', name: 'log4j', version: '1.2.17'

Sravan
  • 596
  • 1
  • 9
  • 19
  • Thank you for reaching out. The above error "Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.logging.log4j.spi.ExtendedLoggerWrapper" on path: DexPathList[[zip " is gone now. But there is a new exception but this doesn't crash app either and connection is not successful yet though. E/System: Uncaught exception thrown by finalizer E/System: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.io.FileDescriptor.isSocket$()' on a null object referenceat sun.nio.ch.FileDispatcherImpl.preCloseImpl(FileDispatcherImpl.java:115) – satya phani Jun 20 '19 at 03:27