B4A Library Socket.IO Client Library

Discussion in 'Additional libraries, classes and official updates' started by Brandsum, Nov 25, 2018.

  1. Brandsum

    Brandsum Active Member Licensed User

    Hi everyone,

    Here is the Socket.IO Client library wrap for this Github Project.

    SocketIOClient
    Author:
    @Brandsum (wrapper)
    Version: 2.4
    Dependency: OkHttpUtils2
    • SocketIOClient
      Method:
      • initialize(EventName As String)
      • connect (host As String, secure As Boolean)
      • connectWithOptions(host As String, secure As Boolean, reconnection As Boolean, reconnectionAttempts As Long, reconnectionDelay As Long, reconnectionDelayMax As Long, timeout As Long)
      • disconnect()
      • emit(event As String, Str As String, multi As Boolean)
      • addEvent(event As String, callback As String)
      • removeEvent(event As String, callback As String)
      • sendAck(ack As Object, data() As Object)
    • Events:
      • OnConnecting: will be raised at the first time it tries to connect to the server
      • OnConnectError(error As Object): will be raised if any error occurs when connecting
      • OnConnectionTimeout(timeout As Object): will be raised if the connection does not receive a response from the server after approximately 30 seconds
      • OnConnect: will be raised on successful connection
      • OnDisconnect(reason As Object): will be raised on connection disconnect. If the disconnection was initiated by the server, you need to reconnect manually else it will try itself to reconnect
      • OnReconnectAttempt(attemptNumber As Object): will be raised if it tries to reconnect after connection timeout or if connection disconnected from client side
      • OnReconnecting(attemptNumber As Object): will be raised on reconnection attempt
      • OnReconnect(attemptNumber As Object): will be raised on successful connection after connection timeout or if connection disconnected from client side
      • OnReconnectError(error As Object): will be raised if any error occurs when reconnecting
      • OnReconnectFailed: will be raised if when couldn’t reconnect within reconnectionAttempts
      • OnError(error As Object): will be raised if any error occurs

    Example Attached.
    For the server code you can check Socket.IO Github example or you can use this following chat server example (written in javascript) [attached]:

    PHP:
    var express = require('express');
    var 
    app express();

    // *** FOR HTTPS CONNECTION *** //
    // const fs = require('fs');

    // var options = {
    //   key: fs.readFileSync('./key.pem'),
    //   cert: fs.readFileSync('./cert.pem'),
    //   passphrase: "password of cert/key file"
    // };

    // var server = require('https').createServer(options, app);
    // *** FOR HTTPS CONNECTION *** //


    // *** FOR HTTP CONNECTION *** //
    var server = require('http').Server(app);
    // *** FOR HTTP CONNECTION *** //

    var io = require('socket.io')(server);
    var 
    users = {};


    server.listen(999, function(){
      
    console.log('listening on *:999');
    });

    io.sockets.on('connection', function(socket){
        
    console.log("User Connected");
     
        
    socket.on('user_msg', function(data,callback){
            
    io.emit('new_message'data);
            
    callback("Data Received");
        });

        
    socket.on('disconnect', function(data){
            
    console.log('User disconnected');
        });
    });
    To run this example server code:
    1. Download NodeJS.
    2. Install it.
    3. Download library zip file and extract.
    4. Run cmd inside server folder
    5. Run npm install
    6. It will take some time to complete.
    7. After that run node app.js
    8. It will show listening on *:999
    9. Now create you app and connect.
    10. That's it!
    11. If you want to use HTTPS (secure connection) then for testing you can generate key and cert file using openssl
      Eg:
      openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
    Update v2:
    1. Now you can declare this in process_globals
    2. Some event signature has been modified (please check above)
    3. New event added OnError
    Update v2.1:
    1. Conflict with B4A OkHttpUtils2 library (Fixed)
    Update v2.2:
    1. Added support for secure connection.
    Update v2.3:
    1. Now you can detect data delivery via acknowledgment of emit event (Check Attached Example).
    Update v2.4:
    1. Send acknowledgment with data to the server on receiving a message.
     

    Attached Files:

    Last edited: Jun 5, 2019
  2. QuentinB3

    QuentinB3 New Member Licensed User

    Hi

    What's the possibility of using this library in a Service Module?
     
  3. DonManfred

    DonManfred Expert Licensed User

    Are you using it in a service and have any error?
    Note that the Serverpart can not be done in B4A. Only the Clientpart but this should work in a Service.
     
  4. QuentinB3

    QuentinB3 New Member Licensed User

    I'm using it in an app. But if I Dim SocketIOClient in Process Globals it gives an error "Cannot access activity object from sub Process_Globals". If I do it inside service_Create it fails at runtime.
     
  5. Brandsum

    Brandsum Active Member Licensed User

    Can you post the error log?
     
  6. QuentinB3

    QuentinB3 New Member Licensed User

    java.lang.NullPointerException
    at com.brandsum.socketio.SocketIO$10.call(SocketIO.java:84)
    at io.socket.emitter.Emitter.emit(Emitter.java:117)
    at io.socket.client.Socket.access$601(Socket.java:24)
    at io.socket.client.Socket$5.run(Socket.java:186)
    at io.socket.thread.EventThread.exec(EventThread.java:55)
    at io.socket.client.Socket.emit(Socket.java:182)
    at io.socket.client.Socket$3.run(Socket.java:144)
    at io.socket.thread.EventThread$2.run(EventThread.java:80)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    at java.lang.Thread.run(Thread.java:838)
     
  7. Brandsum

    Brandsum Active Member Licensed User

    Can you post full error log and your code in using [ code ] tag?
    Are you getting this error while sending (emitting) something?
     
  8. QuentinB3

    QuentinB3 New Member Licensed User

    Code:
    #Region  Service Attributes 
        
    #StartAtBoot: False
       
    #End Region

    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'These variables can be accessed from all modules.
        Dim dit As PhoneEvents
    End Sub

    Sub Service_Create
        dit.Initialize(
    "PhoneEvents")
        
    Dim socket As SocketIOClient
        
    socket.connect("http://172.16.1.72:3000/")
        
    socket.emit("battery_update","30",False)

       
    End Sub

    Sub Service_Start (StartingIntent As Intent)
    '    Dim socket1 As SocketIOClient
    End Sub

    Sub Service_Destroy

    End Sub

    Sub PhoneEvents_BatteryChanged(Level As Int, Scale As Int, Plugged As Boolean, Intent As Intent)
       
        
    Log("BatteryChanged: Level = " & Level & ", Scale = " & Scale & ", Plugged = " & Plugged)
        
    Dim StrLevel = " " & Level
        Main.BatteryLevel = Level
    End Sub

    Sub PhoneEvents_ConnectivityChanged (NetworkType As String, State As StringIntent As Intent)
        
    Log("ConnectivityChanged: " & NetworkType & ", state = " & State)
        
    Log(Intent.ExtrasToString)
    End Sub
    Code:
    ** Activity (main) Create, isFirst = true **
    Event iam data 16118
    ** 
    Activity (main) Resume **
    ** 
    Service (oplaaidat) Create **
    ** 
    Service (oplaaidat) Start **
    ConnectivityChanged: WIFI, state = CONNECTED
    BatteryChanged: Level = 
    48, Scale = 100, Plugged = true
    ** 
    Service (httputils2service) Create **
    ** 
    Service (httputils2service) Start **
    ** 
    Service (httputils2service) Start **
    ** 
    Service (httputils2service) Start **
    BatteryChanged: Level = 
    48, Scale = 100, Plugged = true
    java.lang.NullPointerException
        at com.brandsum.socketio.SocketIO$
    10.call(SocketIO.java:84)
        at io.socket.emitter.Emitter.emit(Emitter.java:
    117)
        at io.socket.client.Socket.access$
    601(Socket.java:24)
        at io.socket.client.Socket$
    5.run(Socket.java:186)
        at io.socket.thread.EventThread.exec(EventThread.java:
    55)
        at io.socket.client.Socket.emit(
    Socket.java:182)
        at io.socket.client.Socket$
    3.run(Socket.java:144)
        at io.socket.thread.EventThread$
    2.run(EventThread.java:80)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:
    1080)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:
    573)
        at java.lang.Thread.run(
    Thread.java:838)
    ** 
    Activity (main) Pause, UserClosed = true **
    Connection established
    java.lang.NullPointerException
        at com.brandsum.socketio.SocketIO$
    9.call(SocketIO.java:90)
        at io.socket.emitter.Emitter.emit(Emitter.java:
    117)
        at io.socket.client.Socket.access$
    601(Socket.java:24)
        at io.socket.client.Socket$
    5.run(Socket.java:186)
        at io.socket.thread.EventThread.exec(EventThread.java:
    55)
        at io.socket.client.Socket.emit(
    Socket.java:182)
        at io.socket.client.Socket.onconnect(
    Socket.java:389)
        at io.socket.client.Socket.onpacket(
    Socket.java:283)
        at io.socket.client.Socket.access$
    100(Socket.java:24)
        at io.socket.client.Socket$
    2$2.call(Socket.java:120)
        at io.socket.emitter.Emitter.emit(Emitter.java:
    117)
        at io.socket.client.Manager.ondecoded(Manager.java:
    427)
        at io.socket.client.Manager.access$
    1600(Manager.java:30)
        at io.socket.client.Manager$
    7.call(Manager.java:403)
        at io.socket.parser.IOParser$Decoder.add(IOParser.java:
    105)
        at io.socket.client.Manager.ondata(Manager.java:
    419)
        at io.socket.client.Manager.access$
    1000(Manager.java:30)
        at io.socket.client.Manager$
    2.call(Manager.java:370)
        at io.socket.emitter.Emitter.emit(Emitter.java:
    117)
        at io.socket.engineio.client.Socket.onPacket(
    Socket.java:551)
        at io.socket.engineio.client.Socket.access$
    1000(Socket.java:36)
        at io.socket.engineio.client.Socket$
    5.call(Socket.java:335)
        at io.socket.emitter.Emitter.emit(Emitter.java:
    117)
        at io.socket.engineio.client.Transport.onPacket(Transport.java:
    126)
        at io.socket.engineio.client.transports.Polling.access$
    700(Polling.java:18)
        at io.socket.engineio.client.transports.Polling$
    2.call(Polling.java:127)
        at io.socket.engineio.parser.Parser.decodePayload(Parser.java:
    241)
        at io.socket.engineio.client.transports.Polling._onData(Polling.java:
    135)
        at io.socket.engineio.client.transports.Polling.onData(Polling.java:
    102)
        at io.socket.engineio.client.transports.PollingXHR$
    5$1.run(PollingXHR.java:125)
        at io.socket.thread.EventThread$
    2.run(EventThread.java:80)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:
    1080)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:
    573)
        at java.lang.Thread.run(
    Thread.java:838)
     
  9. Brandsum

    Brandsum Active Member Licensed User

    Code:
    Sub Service_Create
        dit.Initialize(
    "PhoneEvents")
        
    Dim socket As SocketIOClient
        
    socket.initialize("eventName"'<- Initialize before connecting
        socket.connect("http://172.16.1.72:3000/")
        
    'socket.emit("battery_update","30",False) '<-- you should call this after connection established
    End Sub
    You should initialize first and wait for the connection. After successful connection emit whatever you want. If you want to use it in service SocketIOClient should be declared in Process_Global. I know this is an Activity Object so you can't do this at this moment.

    I'll work on this issue tonight.
     
    DonManfred likes this.
  10. Brandsum

    Brandsum Active Member Licensed User

    Hi @QuentinB3 , That problem has been fixed. Now you can declare SocketIO in process_globals. I've uploaded v2. Please download and replace with previous one.
     
    inakigarm likes this.
  11. fbritop

    fbritop Active Member Licensed User

    Any help with this conflict?

    Code:
    Uncaught translation error: java.lang.IllegalArgumentException: already added: Lokhttp3/Cache$CacheRequestImpl$1;
    Uncaught translation error: java.lang.IllegalArgumentException: already added: Lokhttp3/
    Cache$CacheResponseBody;
    UNEXPECTED TOP-LEVEL 
    EXCEPTION:
    java.lang.RuntimeException: Translation has been interrupted
        at com.android.dx.command.dexer.Main.processAllFiles(Main.java:
    692)
        at com.android.dx.command.dexer.Main.runMonoDex(Main.java:
    315)
        at com.android.dx.command.dexer.Main.runDx(Main.java:
    293)
        at com.android.dx.command.dexer.Main.main(Main.java:
    249)
        at com.android.dx.command.Main.main(Main.java:
    94)
    Caused by: java.lang.InterruptedException: Too many errors
        at com.android.dx.command.dexer.Main.processAllFiles(Main.java:
    684)
        ... 
    4 more
    Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=
    true
    Using:
    upload_2019-2-22_19-8-39.png

    Thanks!
    FBP
     
  12. fbritop

    fbritop Active Member Licensed User

    Solved... by removing dependencies on SocketIOClient.xml

    Code:
    <dependsOn>okhttp-3.8.1</dependsOn>
        <dependsOn>okio-
    1.13.0</dependsOn>
     
  13. Brandsum

    Brandsum Active Member Licensed User

    engine.io client library version 1.0.0 is depend on okhttp3.8.1. So removing those is not a good idea.
    https://mvnrepository.com/artifact/io.socket/engine.io-client/1.0.0

    Actually current version of okhttp library of B4A use okhttp-3.5.0. I'll modify the library to support current B4A okhttp library.
     
  14. Brandsum

    Brandsum Active Member Licensed User

    Hi, @fbritop now you can use SocketIOClient with OkHttpUtils2. That conflict issue has been resolved. You need to remove all previous jar files and extract the attached zipped jar files.
     
    Last edited: Feb 27, 2019
    fbritop and OliverA like this.
  15. Baboooin

    Baboooin New Member Licensed User

    Good day!
    How can I use ssl connection?
     
  16. Brandsum

    Brandsum Active Member Licensed User

    Please check the latest update for SSL connection support and example.
     
  17. Baboooin

    Baboooin New Member Licensed User

    Good day!

    Can I pass Header 'Authorization': 'Bearer abc'? How to do it ?
     
  18. fbritop

    fbritop Active Member Licensed User

    Is it possible to reply to an incoming message directly over the message?. I have done it with nodejs socketio Client in linux. So when I receive a command, it issues a callback over the same message:

    A node JS gets a rest request, so it emits a message to a device, and wait for the callback from the device before sending the reply back to the REST request

    Server:
    Code:
    devices[queryData.idDevice].emit('open', data, function (retorno) {
       var now2 = new Date();
       var now3 = (now2-now)/
    1000
       var now4=Math.round(now3*
    10)/10
       logg(logDate() + 
    "CMD ACK IN " + now4 + "s! (" + now3 + ")")
       logg(logDate() + retorno);
       res.end(retorno);
       
    return;
    })

    Client:
    Code:
    socket.on('open', function(data, fn){
        log(chalk.green.bold("Open CMD RX"));
        fn(
    '{"code":"answer","resultCode":0,"result":"ACK"}');
    })
    Not sure if it can be done with this library.
    Thanks in advance
     
  19. Brandsum

    Brandsum Active Member Licensed User

    That is not possible yet. Currently emit method will raise an acknowledgment event. Sending acknowledgment on message received will be added in next update. May be today or tomorrow.
     
  20. fbritop

    fbritop Active Member Licensed User

    Thanks @Brandsum. One thing I noticed, if i do the server emit with callback, then the event signature changes (it throw me an error at first), so I added a second object to the sub signature on B4A and it pass. When I checked the getType of the second signature object, it was a socketIOClient type, but the only method I could execute with no error on that socket was the disconnect method. So under that situation, I can see that the original library is receiveing the callback object.

    Thanks for the update in advance.
    FBP
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice