web-dev-qa-db-fra.com

Comment garder le client Android connecté au serveur même en cas de changement d'activité et envoyer des données au serveur?

J'ai initialement implémenté une tâche asynchrone dans mon activité qui envoie des données au serveur. Mais quand j'ai changé d'activité, la connexion a été perdue. Pour éviter cela, mon approche a été de mettre en œuvre un service qui centralise le fonctionnement du réseau et envoie des données au serveur et le code de ce service est donné ci-dessous

import Java.io.BufferedWriter;
import Java.io.OutputStreamWriter;
import Java.io.PrintWriter;
import Java.net.InetAddress;
import Java.net.Socket;

import Android.app.Service;
import Android.content.Intent;
import Android.os.Binder;
import Android.os.IBinder;
import Android.util.Log;
import Android.widget.Toast;

public class SocketService extends Service {
  public static final String SERVERIP = ""; //your computer IP address should be written here
  public static final int SERVERPORT = 5000;
  PrintWriter out;
  Socket socket;
  InetAddress serverAddr;

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    System.out.println("I am in Ibinder onBind method");
      return myBinder;
}

  private final IBinder myBinder = new LocalBinder();
  TCPClient mTcpClient = new TCPClient();

  public class LocalBinder extends Binder {
        public SocketService getService() {
            System.out.println("I am in Localbinder ");
            return SocketService.this;

        }
    }

  @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("I am in on create");     
    }

  public void IsBoundable(){
        Toast.makeText(this,"I bind like butter", Toast.LENGTH_LONG).show();
    }

  public void sendMessage(String message){
        if (out != null && !out.checkError()) {
            System.out.println("in sendMessage"+message);
            out.println(message);
            out.flush();
        }
    }

    @Override
    public int onStartCommand(Intent intent,int flags, int startId){
        super.onStartCommand(intent, flags, startId);
        System.out.println("I am in on start");
      //  Toast.makeText(this,"Service created ...", Toast.LENGTH_LONG).show();
        Runnable connect = new connectSocket();
        new Thread(connect).start();
        return START_STICKY;
    }


    class connectSocket implements Runnable {

        @Override
        public void run() {


            try { 
                 //here you must put your computer's IP address.
                serverAddr = InetAddress.getByName(SERVERIP);
                Log.e("TCP Client", "C: Connecting...");
                //create a socket to make the connection with the server

                socket = new Socket(serverAddr, SERVERPORT);

                 try {


                     //send the message to the server
                     out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);


                     Log.e("TCP Client", "C: Sent.");

                     Log.e("TCP Client", "C: Done.");


                    } 
                 catch (Exception e) {

                     Log.e("TCP", "S: Error", e);

                 }
            } catch (Exception e) {

                Log.e("TCP", "C: Error", e);

            }

        }

    }


    @Override
    public void onDestroy() {
        super.onDestroy();
          try {
              socket.close();
          } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
          socket = null;
      }


    }

Rotator.Java est mon activité que je lie à ce service. Voici quelques morceaux de code de mon activité.

private ServiceConnection mConnection = new ServiceConnection() {
            //EDITED PART
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // TODO Auto-generated method stub
         mBoundService = ((SocketService.LocalBinder)service).getService();

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        // TODO Auto-generated method stub
         mBoundService = null;
    }

  };


   private void doBindService() {
       bindService(new Intent(Rotator.this, SocketService.class), mConnection, Context.BIND_AUTO_CREATE);
       mIsBound = true;
       if(mBoundService!=null){
       mBoundService.IsBoundable();
       }
   }


   private void doUnbindService() {
       if (mIsBound) {
           // Detach our existing connection.
           unbindService(mConnection);
           mIsBound = false;
       }
   }

@Override
public void onCreate(Bundle savedInstanceState)
{
      super.onCreate(savedInstanceState);
      gestureDetector = new GestureDetector(this, new GestureListener());
      setContentView(R.layout.activity_rotator);


      //Binding the activity to the service to perform client-server operations
      //start service on create
        startService(new Intent(Rotator.this,SocketService.class));
        doBindService();
                  ...........
                  ...........
}   


@Override
protected void onDestroy() {
    super.onDestroy();
    doUnbindService();
}

Maintenant que ce service fonctionne en arrière-plan, si je veux envoyer des données au serveur, j'utilise ce qui suit

 if(mBoundService!=null)
{
    mBoundService.sendMessage("right");
}
22
gfernandes

Le code est juste. La seule erreur était que j'essayais de démarrer le service deux fois une fois dans la méthode onServiceConnected () et l'autre dans la méthode onCreate ().

J'ai changé mon code pour démarrer le service uniquement dans la méthode onCreate () dans l'activité du lanceur. Les autres activités se lient directement au service à l'aide de la méthode doBindService ()

7
gfernandes

Lorsqu'un service est lié à un Activity, il est tué lorsque l'activité est arrêtée, c'est comme un service d'arrière-plan uniquement pour le Activity. Par conséquent, pour continuer à fonctionner, implémentez la méthode onStartCommand() dans votre classe Service et retournez this.START_STICKY. et gérez votre service dans cette méthode.

2
AbdulHannan