web-dev-qa-db-ja.com

アクティビティの変更があってもAndroidクライアントをサーバーに接続し、サーバーにデータを送信する方法は?

最初に、サーバーにデータを送信するアクティビティに非同期タスクを実装しました。しかし、アクティビティを変更すると接続が失われました。これを回避するために、私のアプローチは、ネットワーク操作を集中化してサーバーにデータを送信するサービスを実装することでした。このサービスのコードは以下のとおりです。

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は、このサービスにバインドするアクティビティです。以下は私の活動からのコードの一部です。

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();
}

このサービスはバックグラウンドで実行されるため、サーバーにデータを送信する場合は次を使用します

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

コードは正しいです。唯一の間違いは、onServiceConnected()メソッドで1回、onCreate()メソッドでもう1回サービスを開始しようとしていたことです。

ランチャーアクティビティのonCreate()メソッドでのみサービスを開始するようにコードを変更しました。残りのアクティビティは、doBindService()メソッドを使用してサービスに直接バインドします

7
gfernandes

サービスがActivityにバインドされている場合、アクティビティが停止すると強制終了されます。これはActivityのみのバックグラウンドサービスのようです。したがって、実行し続けるには、ServiceクラスにonStartCommand()メソッドを実装し、this.START_STICKY。この方法でサービスを管理します。

2
AbdulHannan