Android Tutorial [B4X] MQTT Chat Room

Status
Not open for further replies.
It's time to learn how to use MQTT: https://www.b4x.com/android/forum/threads/59471/#content
It is simple and powerful. In most cases MQTT is the best solution for low level networks. Low level network means a network solution that is traditionally based on ServerSocket + Socket + AsyncStreams.

In this example we implement a chat room with one or more users. The MQTT broker is embedded in the Android app (jMqttBroker library). The clients are Android, iOS or desktop apps. Any number of users can join.


upload_2015-12-21_14-42-4.png
upload_2015-12-21_14-43-50.png


SS-2015-12-21_14.40.07.png


When you start the Android app you can choose whether it will be the server. The other clients will connect to the server.

The messages are serialized with B4XSerializator (RandomAccessFile library). B4XSerializator is very useful for cross platform communication.

Users can join and leave the chat room. The list of users will be updated automatically.
Note the usage of the LastWill feature. When a client is disconnected unexpectedly (and only if it is unexpectedly) the LastWill message will be sent. This allows us to remove the client from the list.

The UI state is managed by StateManager (in B4A and B4i).
It is a simple and flexible UI implemented with anchors. Note that it properly handles the soft keyboard changes.

jMQTT library: https://www.b4x.com/android/forum/threads/59472/#content
jMqttBroker: https://www.b4x.com/android/forum/threads/mqttbroker.61548

Extension to this example with auto discovery: https://www.b4x.com/android/forum/posts/480542/
 

Attachments

  • Chat_B4i.zip
    6.1 KB · Views: 2,274
  • Chat_B4J.zip
    3.8 KB · Views: 3,607
  • Chat_B4A.zip
    11.3 KB · Views: 2,828
Last edited:

MarcoRome

Expert
Licensed User
Longtime User
I'm trying to make a connection Internet using the service cloudmqtt.com

Screenshot 2015-12-21 18.56.23.png


So after registrared and watched the documentation, i tried the same server access in B4A.

Screenshot 2015-12-21 18.59.10.png


i read this:
....The instance is immediately provisioned after sign up and you can view the instance details, such as connection information, at the details page. You can also reach the Management interface from there. Sometimes you need to use a specify a connection URL, it should look like
mqtt://user:password@server:port

i have this code:

B4X:
....
client.Initialize("client", $"mqtt://${Name}:${pw}@${Host}:${port}"$, "android" & Rnd(1, 10000000))
......

Code complete:

B4X:
Public Sub ConnectTo(Host As String, Name As String)
    currentName = Name
    isServer = Host = "127.0.0.1" 'Local
    If isServer Then
        If brokerStarted = False Then
            broker.Start
            brokerStarted = True
        End If
        users.Clear
        Host = "127.0.0.1" 'Locale
    End If
    If connected Then client.Close
    Dim pw As String = "F03GRGqVzsWf"
    'client.Initialize("client", $"tcp://${Host}:${port}"$, "android" & Rnd(1, 10000000)) 'Local
    client.Initialize("client", $"mqtt://${Name}:${pw}@${Host}:${port}"$, "android" & Rnd(1, 10000000))
    Dim mo As MqttConnectOptions
    mo.Initialize("", "")
    'this message will be sent if the client is disconnected unexpectedly.
    mo.SetLastWill("all/disconnect", serializator.ConvertObjectToBytes(currentName), 0, False)
    client.Connect2(mo)
End Sub

When i try connect my devices in internet i have this error:

Screenshot 2015-12-21 19.04.09.png


Log:

Installing file.
PackageAdded: package:b4a.chat
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
starter_connectto (B4A line: 43)
client.Initialize("client", $"mqtt://${Name}:${pw
java.lang.IllegalArgumentException: mqtt://test1:F03GRGqVzsWf@m10.cloudmqtt.com:34508
at org.eclipse.paho.client.mqttv3.MqttConnectOptions.validateURI(MqttConnectOptions.java:470)
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.<init>(MqttAsyncClient.java:273)
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.<init>(MqttAsyncClient.java:167)
at anywheresoftware.b4j.objects.MqttAsyncClientWrapper.Initialize(MqttAsyncClientWrapper.java:42)
at b4a.chat.starter._connectto(starter.java:342)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:897)
at anywheresoftware.b4a.keywords.Common.CallSubNew3(Common.java:847)
at b4a.chat.main._btnconnect_click(main.java:454)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:78)
at android.view.View.performClick(View.java:4659)
at android.view.View$PerformClick.run(View.java:19462)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5692)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)

Where i wrong ??
Thank you
Marco
 

aidymp

Well-Known Member
Licensed User
Longtime User
is this only for the latest version of B4A? i dont have the money to upgrade yet hopefully Santa will sort that out? i belive my randomaccessfile lib is out of date!

b4a.png
 

MarcoRome

Expert
Licensed User
Longtime User
Strain that dont work about 5.20 but anyway
this is the best gift that you can do :) "B4X is the best gift"
 

javiers

Active Member
Licensed User
Longtime User
Error connecting ... Android


B4X:
Copying updated assets files (1)
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = false **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = false **
** Activity (main) Resume **
Error occurred on line: 33 (Starter)
java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.keywords.Common.CallSubDebug3(Common.java:862)
    at b4a.example.main._btnconnect_click(main.java:444)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:697)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:78)
    at android.view.View.performClick(View.java:4211)
    at android.view.View$PerformClick.run(View.java:17446)
    at android.os.Handler.handleCallback(Handler.java:725)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:153)
    at android.app.ActivityThread.main(ActivityThread.java:5297)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:336)
    at anywheresoftware.b4a.debug.Debug.CallSubNew3(Debug.java:288)
    ... 26 more
Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:318)
    ... 27 more
Caused by: java.lang.RuntimeException: java.lang.ExceptionInInitializerError
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:165)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:262)
    at b4a.example.starter._connectto(starter.java:130)
    ... 30 more
Caused by: java.lang.ExceptionInInitializerError
    at com.lmax.disruptor.RingBufferFields.<clinit>(RingBuffer.java:34)
    at com.lmax.disruptor.dsl.Disruptor.<init>(Disruptor.java:80)
    at org.eclipse.moquette.spi.impl.SimpleMessaging.init(SimpleMessaging.java:99)
    at org.eclipse.moquette.server.Server.startServer(Server.java:93)
    at anywheresoftware.b4j.objects.MqttBroker.Start(MqttBroker.java:71)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:742)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:342)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    ... 32 more
Caused by: java.lang.RuntimeException: Unable to load unsafe
    at com.lmax.disruptor.util.Util.<clinit>(Util.java:112)
    ... 45 more
Caused by: java.security.PrivilegedActionException: java.lang.NoSuchFieldException: theUnsafe
    at java.security.AccessController.doPrivileged(AccessController.java:64)
    at com.lmax.disruptor.util.Util.<clinit>(Util.java:108)
    ... 45 more
Caused by: java.lang.NoSuchFieldException: theUnsafe
    at java.lang.Class.getDeclaredField(Class.java:631)
    at com.lmax.disruptor.util.Util$1.run(Util.java:102)
    at com.lmax.disruptor.util.Util$1.run(Util.java:99)
    at java.security.AccessController.doPrivileged(AccessController.java:60)
    ... 46 mo
Message longer than Log limit (4000). Message was truncated.
An error occurred:
(Line: 34) brokerStarted = True
java.lang.RuntimeException: Array not expected...
 

javiers

Active Member
Licensed User
Longtime User
It is related to the Android version. Which version are you using?

I've made an update. Please download the new jars and try it again: https://www.b4x.com/android/forum/threads/mqttbroker.61548


Hello Erel, I have version 4.2.1 on the phone . I try now with the new jar.

Indeed, now it works with the new jar.

Another question in the broker installed on Android, what is the IP address to be put ?. The internal IP? Can the app to know what is and put it at the beginning of the service? Thanks for your answers.
 
Last edited:

javiers

Active Member
Licensed User
Longtime User
It doesn't matter. You can leave it empty.

Check the code:
B4X:
Dim host As String = txtHost.Text
If rdbServer.Checked Then host = "127.0.0.1"
CallSub3(Starter, "ConnectTo", host, txtName.Text)
Tanks!
 
Status
Not open for further replies.
Top