Autore Topic: Come gestire correttamente un Socket in Android  (Letto 568 volte)

Offline gabdroid

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5 G900F
  • Sistema operativo:
    Windows 7 Professional 64 bit
Come gestire correttamente un Socket in Android
« il: 29 Giugno 2016, 10:43:07 CEST »
0
Buongiorno, sono un neofita di programmazione Android e volevo sapere qual'è il modo migliore per gestire un WebSocket su Android.
In particolare mi interessava capire come rendere disponibile quel determinato WebSocket, che ha stabilito la connessione, a tutte le activity dell'applicazione e come far si che, in caso di WebSocket non più connesso, quest'ultimo ritenti a connettersi fin quando la connessione non sarà nuovamente stabilita.
Grazie in anticipo!
Gabriele.  :-P

Offline tonno16

  • Utente storico
  • *****
  • Post: 1169
  • Respect: +56
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Come gestire correttamente un Socket in Android
« Risposta #1 il: 29 Giugno 2016, 10:47:33 CEST »
0
Personalmente farei un service. lo avvi una volta e basta. Si connette alle socket. Se si notifica all' activity un OK. Se no, setta un alarm manager 10 minuti avanti e poi si autokilla. Il broadcast quando chiamato avvia nuovamente lo stesso service che ovviamente farà la stessa cosa

Offline gabdroid

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5 G900F
  • Sistema operativo:
    Windows 7 Professional 64 bit
Re:Come gestire correttamente un Socket in Android
« Risposta #2 il: 30 Giugno 2016, 18:41:43 CEST »
0
Si ma quando connetto il WebSocket al Server, per renderlo poi accessibile (l'oggetto WebSocket) a tutte le activity in modo da poter comunicare col Server come faccio? Lo metto in un Singleton?
« Ultima modifica: 30 Giugno 2016, 18:51:35 CEST da gabdroid »

Offline LinkOut

  • Utente normale
  • ***
  • Post: 268
  • Respect: +37
    • Mostra profilo
  • Dispositivo Android:
    Xiaomi Mi5
Re:Come gestire correttamente un Socket in Android
« Risposta #3 il: 01 Luglio 2016, 09:05:45 CEST »
0
Buongiorno, sono un neofita di programmazione Android e volevo sapere qual'è il modo migliore per gestire un WebSocket su Android.
In particolare mi interessava capire come rendere disponibile quel determinato WebSocket, che ha stabilito la connessione, a tutte le activity dell'applicazione e come far si che, in caso di WebSocket non più connesso, quest'ultimo ritenti a connettersi fin quando la connessione non sarà nuovamente stabilita.
Grazie in anticipo!
Gabriele.  :-P

Recentemente ho usato https://github.com/socketio/socket.io-client-java, per renderlo disponibile a tutte le activity, il socket lo avvio in una "BaseActivity" la quale tratta tutto quello che riguarda il socket, ed eventualmente agisce, per esempio mostrando alert, siccome le altre activity dell'applicazione estendono la BaseActivity, gli alert vengono mostrati. Il socket in questione quando perde la connesione, ed entra nella callback di errore o timeout, riprova a connettersi tante volte fino a che non "riaggancia" la connessione.

Saluti.

Offline gabdroid

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5 G900F
  • Sistema operativo:
    Windows 7 Professional 64 bit
Re:Come gestire correttamente un Socket in Android
« Risposta #4 il: 01 Luglio 2016, 09:10:54 CEST »
0
Non ho capito cos'è la BaseActivity che intendi te...  :-( Potresti essere più "pratico"?

Offline LinkOut

  • Utente normale
  • ***
  • Post: 268
  • Respect: +37
    • Mostra profilo
  • Dispositivo Android:
    Xiaomi Mi5
Re:Come gestire correttamente un Socket in Android
« Risposta #5 il: 01 Luglio 2016, 09:22:44 CEST »
0
Ok, provo a farti un esempio al volo di come ho implementato quella libreria.

Partiamo dalla BaseActivity (Ovvero l'activity BASE che viene ESTESA da tutte le altre activity dell'applicazione)

Cosa fa questa activity? Implementa un'interfaccia, e istanzia una classe che si occupa della gestione del socket.

Questa è l'interfaccia:

Codice (Java): [Seleziona]
public interface ISocketEvents {

    /**
     * OnSocketConnectionError event
     */

    void onSocketConnectionError();

    /**
     * onSocketConnected event
     */

    void onSocketConnected();

    /**
     * onSocketRegistered event
     * @param object object that actually returns from socket event
     */

    void onSocketRegistered(Object object);

    /**
     * onMessageEvent
     * @param object array of objects that actually returns from socket event
     */

    void onMessageEvent(Object[] object);

    /**
     * Message sent to client tellin if there is any response from the WS! if it's sill alive
     * */

    void connectionIsAlive();

    /**
     * Sendin socket disconnection message
     * */

    void onSocketDisconnected();

    /**
     * Sending connection timeout error!
     * */

    void onSocketConnectionTimeOut();
}

La Base activity, implementando l'interfaccia, implementa di conseguenza tutti i suoi metodi. Questa interfaccia è istanziata dalla classe che si occupa della gestione del socket, la quale appunto manda questi messaggi alla BaseActivity.

SocketHandler:

Codice (Java): [Seleziona]
public class SocketHandler {

    private static String EP_WEBSOCKET = "YourEP";

    ISocketEvents iSocketEvents;

    private Socket mSocket;
    {
        try {
            //IO.Options opts = new IO.Options();
            mSocket = IO.socket(EP_WEBSOCKET);
        } catch (URISyntaxException e) {}
    }

    /**
     * Constructor with Interface init
     * */

    public SocketHandler(ISocketEvents iSocketEvents){
        this.iSocketEvents = iSocketEvents;
    }

    /**
     * Connecting to socket, and start listening on the socket events
     */

    public void connectToSocket () {
        //Connect to socket and start listen on
        mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectionTimeOut);
        mSocket.on(Socket.EVENT_CONNECT, onConnectEvent);
        mSocket.on(Socket.EVENT_DISCONNECT, onDisconnectEvent);
        mSocket.on("anyKind", onMessageEvent);

        mSocket.connect();
    }

    /**
     * Disconnecting from the socket, and removing already listening events
     */

    public void disconnectFromSocket () {
        //Disconnecting everything
        mSocket.disconnect();
        mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectionTimeOut);
        mSocket.off(Socket.EVENT_CONNECT, onConnectEvent);
        mSocket.off(Socket.EVENT_DISCONNECT, onDisconnectEvent);
        mSocket.off("anyKind", onMessageEvent);
    }

    /**
     * Listen on connection error, and notify who's implementing the interface
     */

    private Emitter.Listener onConnectError = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketConnectionError();
        }
    };

    /**
     * Listen on connection error, and notify who's implementing the interface
     */

    private Emitter.Listener onConnectionTimeOut = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketConnectionTimeOut();
        }
    };

    /**
     * Listen on connected event, and notify who's implementing the interface
     * */

    private Emitter.Listener onConnectEvent = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketConnected();
        }
    };

    /**
     * Listen on message event type msg from the socket, and notify who's implementing the interface
     */

    private Emitter.Listener onMessageEvent = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onMessageEvent(args);
        }
    };

    /**
     * Listen on disconnect event, and notify who's implementing the interface
     * */

    private Emitter.Listener onDisconnectEvent = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketDisconnected();
        }
    };

    /**
     * Registering to the socket via this method, each time we connect to socket
     * @param token Used in session
     */

    public void registerToSocket(String token) {
        mSocket.emit("register", token, new Ack() {
            @Override
            public void call(Object... args) {
                //args is a JSON Object
                iSocketEvents.onSocketRegistered(args);
            }
        });
    }

}

In questo modo c'è una sola activity che gestisce il socket e si chiama BaseActivity, la quale appunto è implementata dalle altre activity per far sì che possa mostrare messaggi ovunque l'utente si trovi. Per la comunicazione tra activity io consiglio vivamente di usare interfacce. Se per caso tu devi mandare via socket un messaggio proveniente da un activity Pippo, ma il socket è trattato solo dalla BaseActivity (la quale manda il messaggio), allora tramite interfaccia fai "parlare" le due Activity.

Spero di essere stato più chiaro.

Offline gabdroid

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5 G900F
  • Sistema operativo:
    Windows 7 Professional 64 bit
Re:Come gestire correttamente un Socket in Android
« Risposta #6 il: 01 Luglio 2016, 09:47:13 CEST »
0
Allora, la mia app ha 2 activity:
- LoginActivity (che viene visualizzata al lancio dell'applicazione)
- MainActivity (che viene visualizzata alla chiusura di LoginActivity)

Quindi da quanto ho capito devo implementare l'interfaccia ISocketEvents su LoginActivity e poi non ho capito... Devo creare un'oggetto SocketHandler passandogli "this" come argomento?

Offline gabdroid

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5 G900F
  • Sistema operativo:
    Windows 7 Professional 64 bit
Re:Come gestire correttamente un Socket in Android
« Risposta #7 il: 05 Luglio 2016, 14:39:21 CEST »
0
Ok, provo a farti un esempio al volo di come ho implementato quella libreria.

Partiamo dalla BaseActivity (Ovvero l'activity BASE che viene ESTESA da tutte le altre activity dell'applicazione)

Cosa fa questa activity? Implementa un'interfaccia, e istanzia una classe che si occupa della gestione del socket.

Questa è l'interfaccia:

Codice (Java): [Seleziona]
public interface ISocketEvents {

    /**
     * OnSocketConnectionError event
     */

    void onSocketConnectionError();

    /**
     * onSocketConnected event
     */

    void onSocketConnected();

    /**
     * onSocketRegistered event
     * @param object object that actually returns from socket event
     */

    void onSocketRegistered(Object object);

    /**
     * onMessageEvent
     * @param object array of objects that actually returns from socket event
     */

    void onMessageEvent(Object[] object);

    /**
     * Message sent to client tellin if there is any response from the WS! if it's sill alive
     * */

    void connectionIsAlive();

    /**
     * Sendin socket disconnection message
     * */

    void onSocketDisconnected();

    /**
     * Sending connection timeout error!
     * */

    void onSocketConnectionTimeOut();
}

La Base activity, implementando l'interfaccia, implementa di conseguenza tutti i suoi metodi. Questa interfaccia è istanziata dalla classe che si occupa della gestione del socket, la quale appunto manda questi messaggi alla BaseActivity.

SocketHandler:

Codice (Java): [Seleziona]
public class SocketHandler {

    private static String EP_WEBSOCKET = "YourEP";

    ISocketEvents iSocketEvents;

    private Socket mSocket;
    {
        try {
            //IO.Options opts = new IO.Options();
            mSocket = IO.socket(EP_WEBSOCKET);
        } catch (URISyntaxException e) {}
    }

    /**
     * Constructor with Interface init
     * */

    public SocketHandler(ISocketEvents iSocketEvents){
        this.iSocketEvents = iSocketEvents;
    }

    /**
     * Connecting to socket, and start listening on the socket events
     */

    public void connectToSocket () {
        //Connect to socket and start listen on
        mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectionTimeOut);
        mSocket.on(Socket.EVENT_CONNECT, onConnectEvent);
        mSocket.on(Socket.EVENT_DISCONNECT, onDisconnectEvent);
        mSocket.on("anyKind", onMessageEvent);

        mSocket.connect();
    }

    /**
     * Disconnecting from the socket, and removing already listening events
     */

    public void disconnectFromSocket () {
        //Disconnecting everything
        mSocket.disconnect();
        mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectionTimeOut);
        mSocket.off(Socket.EVENT_CONNECT, onConnectEvent);
        mSocket.off(Socket.EVENT_DISCONNECT, onDisconnectEvent);
        mSocket.off("anyKind", onMessageEvent);
    }

    /**
     * Listen on connection error, and notify who's implementing the interface
     */

    private Emitter.Listener onConnectError = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketConnectionError();
        }
    };

    /**
     * Listen on connection error, and notify who's implementing the interface
     */

    private Emitter.Listener onConnectionTimeOut = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketConnectionTimeOut();
        }
    };

    /**
     * Listen on connected event, and notify who's implementing the interface
     * */

    private Emitter.Listener onConnectEvent = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketConnected();
        }
    };

    /**
     * Listen on message event type msg from the socket, and notify who's implementing the interface
     */

    private Emitter.Listener onMessageEvent = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onMessageEvent(args);
        }
    };

    /**
     * Listen on disconnect event, and notify who's implementing the interface
     * */

    private Emitter.Listener onDisconnectEvent = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            iSocketEvents.onSocketDisconnected();
        }
    };

    /**
     * Registering to the socket via this method, each time we connect to socket
     * @param token Used in session
     */

    public void registerToSocket(String token) {
        mSocket.emit("register", token, new Ack() {
            @Override
            public void call(Object... args) {
                //args is a JSON Object
                iSocketEvents.onSocketRegistered(args);
            }
        });
    }

}

In questo modo c'è una sola activity che gestisce il socket e si chiama BaseActivity, la quale appunto è implementata dalle altre activity per far sì che possa mostrare messaggi ovunque l'utente si trovi. Per la comunicazione tra activity io consiglio vivamente di usare interfacce. Se per caso tu devi mandare via socket un messaggio proveniente da un activity Pippo, ma il socket è trattato solo dalla BaseActivity (la quale manda il messaggio), allora tramite interfaccia fai "parlare" le due Activity.

Spero di essere stato più chiaro.

Allora, la mia app ha 2 activity:
- LoginActivity (che viene visualizzata al lancio dell'applicazione)
- MainActivity (che viene visualizzata alla chiusura di LoginActivity)

Quindi da quanto ho capito devo implementare l'interfaccia ISocketEvents su LoginActivity e poi non ho capito... Devo creare un'oggetto SocketHandler passandogli "this" come argomento?

Offline LinkOut

  • Utente normale
  • ***
  • Post: 268
  • Respect: +37
    • Mostra profilo
  • Dispositivo Android:
    Xiaomi Mi5
Re:Come gestire correttamente un Socket in Android
« Risposta #8 il: 05 Luglio 2016, 15:11:08 CEST »
0
Ciao, il mio era un esempio per farti capire come potresti implementare una comunicazione via Socket, non devi copiare cosa ti ho scritto lì ma usarlo come esempio. Come ti ho scritto nel post precedente, l'esempio postato è specifico per un mio caso d'uso. Non so te come devi usare il socket.

Offline gabdroid

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5 G900F
  • Sistema operativo:
    Windows 7 Professional 64 bit
Re:Come gestire correttamente un Socket in Android
« Risposta #9 il: 05 Luglio 2016, 15:16:04 CEST »
0
Ciao, il mio era un esempio per farti capire come potresti implementare una comunicazione via Socket, non devi copiare cosa ti ho scritto lì ma usarlo come esempio. Come ti ho scritto nel post precedente, l'esempio postato è specifico per un mio caso d'uso. Non so te come devi usare il socket.
Intanto grazie per la risposta.
Comunque sì, avevo capito, ma volevo capire se l'esempio che mi avevi postato te si doveva applicare in questo modo  :-P

Offline LinkOut

  • Utente normale
  • ***
  • Post: 268
  • Respect: +37
    • Mostra profilo
  • Dispositivo Android:
    Xiaomi Mi5
Re:Come gestire correttamente un Socket in Android
« Risposta #10 il: 05 Luglio 2016, 15:27:23 CEST »
0
Con BaseActivity io intendo un'activity che non si chiude mai se non con la chiusura dell'applicazione (Come potrebbe essere la MainActivity), se usi il socket sull'activity di login che presumibilmente dopo che ha fatto "il suo dovere" si chiude tramite finish(); non ha tanto senso...

Il socket io lo userei sulla MainActivity, la quale implementa l'interfaccia (così da poter passare this alla classe SocketHandler)...


Codice (Java): [Seleziona]
public class MainActivity extends AppCompatActivity implements ISocketEvents {

  private SocketHandler mSocketHandler;
               

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSocketHandler = new SocketHandler(this); //Perchè appunto la classe implementa l'interfaccia ;)
     }
               
}

Offline gabdroid

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5 G900F
  • Sistema operativo:
    Windows 7 Professional 64 bit
Re:Come gestire correttamente un Socket in Android
« Risposta #11 il: 05 Luglio 2016, 15:40:01 CEST »
0
Sì ma nell'activity del login come faccio poi ad inviare i dati di accesso al Server se la connessione è gestita solo dalla MainActivity?

Offline LinkOut

  • Utente normale
  • ***
  • Post: 268
  • Respect: +37
    • Mostra profilo
  • Dispositivo Android:
    Xiaomi Mi5
Re:Come gestire correttamente un Socket in Android
« Risposta #12 il: 05 Luglio 2016, 15:45:16 CEST »
0
Non so cosa tu debba fare, ma solitamente una Login si fa con una chiamata di tipo POST, dove tu nel body setti username & password (o non so qualunque tuo metodo di auth) e il server ti risponde successo o no ....