2016-09-28 2 views
-3

Я пытаюсь создать простое приложение, которое отправляет сообщение от EditText, с использованием класса Java Socket. Я пытаюсь с AsyncTask, но он работает только один раз, и я не могу вернуть сокет для повторного использования в другой экземпляр класса.Как подключиться к сокету на Android

Можете ли вы привести мне пример фоновой службы, которая открывает связь с сервером и возвращает Socket?

РЕДАКТИРОВАТЬ:
В соответствии с требованиями nandsito; Я намерен открыть соединение с помощью Button, поэтому эта кнопка вызывает beckground-процесс, который создает соединение с сервером, и, наконец, возвращает Socket. Когда я нажимаю другой Button, я хочу запустить другую задачу, которая повторно использует сокеты, записывать данные (например, Sring), получать ответ от сервера и обновлять интерфейс.

+0

я обновил свой ответ, пожалуйста, посмотрите – nandsito

ответ

0

Это выглядит просто, но я думаю, у вас есть интересная и сложная проблема. Если вы хотите сохранить сокет открытым после отправки сообщений через него, вам нужно будет поддерживать один или несколько потоков для использования этого сокета, потому что, как вы знаете, Android не разрешает создавать сети в основном потоке.

Многопоточное программирование редко бывает простым и часто существует несколько способов сделать это. Например. в Android вы можете использовать Handler s с Looper s от HandlerThread s или классической Java Thread. А также AsyncTask, но я думаю, что это не подходит для этого случая.

Как вы собираетесь управлять жизненным циклом сокета (т. Е. Когда он открыт или закрыт), и в каких моментах данные считываются/записываются из/в сокет? Пожалуйста, объясните лучше, поэтому я могу предложить реализацию.

EDIT

Вот пример Activity с двумя кнопками. Одна кнопка запускает AsyncTask, которая создает сокет и его потоки, а другая кнопка запускает еще один AsyncTask, который записывает данные в сокет. Это упрощенное решение, но оно должно работать. Обратите внимание, что для этого кода требуется синхронизации, для разных потоков доступ к сокету.

public class MainActivity extends Activity { 

    private SocketContainer mSocketContainer; 
    private final Object mSocketContainerLock = new Object(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
    } 

    // onClick attribute of one button. 
    public void onClickPushMe(View view) { 
     String serverAddress; 
     int serverPort; 
     new CreateSocketAsyncTask(serverAddress, serverPort).execute(); 
    } 

    // onClick attribute of other button. 
    public void onClickPushMeToo(View view) { 
     String text; 
     new WriteSocketAsyncTask(text).execute(); 
    } 

    // Class that contains the socket and its streams, 
    // so they can be passed from one thread to another. 
    private class SocketContainer { 

     private Socket mSocket; 
     private InputStream mSocketInputStream; 
     private OutputStream mSocketOutputStream; 

     private SocketContainer(Socket socket, InputStream socketInputStream, OutputStream socketOutputStream) { 
      mSocket = socket; 
      mSocketInputStream = socketInputStream; 
      mSocketOutputStream = socketOutputStream; 
     } 

     private Socket getSocket() { 
      return mSocket; 
     } 

     private InputStream getSocketInputStream() { 
      return mSocketInputStream; 
     } 

     private OutputStream getSocketOutputStream() { 
      return mSocketOutputStream; 
     } 
    } 

    // AsyncTask that creates a SocketContainer and sets in into MainActivity. 
    private class CreateSocketAsyncTask extends AsyncTask<Void, Void, SocketContainer> { 

     private final String mServerAddress; 
     private final int mServerPort; 

     private CreateSocketAsyncTask(String serverAddress, int serverPort) { 
      mServerAddress = serverAddress; 
      mServerPort = serverPort; 
     } 

     protected SocketContainer doInBackground(Void... params) { 
      try { 
       Socket socket = new Socket(mServerAddress, mServerPort); 
       return new SocketContainer(socket, socket.getInputStream(), socket.getOutputStream()); 
      } catch (IOException e) { 
       throw new RuntimeException(e); 
      } 
     } 

     @Override 
     protected void onPostExecute(SocketContainer socketContainer) { 
      super.onPostExecute(socketContainer); 
      synchronized (mSocketContainerLock) { 
       mSocketContainer = socketContainer; 
      } 
     } 
    } 

    private class WriteSocketAsyncTask extends AsyncTask<Void, Void, Void> { 

     private final String mText; 

     private WriteSocketAsyncTask(String text) { 
      mText = text; 
     } 

     @Override 
     protected Void doInBackground(Void... params) { 
      synchronized (mSocketContainerLock) { 
       try { 
        mSocketContainer.getSocketOutputStream().write(mText.getBytes(Charset.forName("UTF-8"))); 
        mSocketContainer.getSocketOutputStream().flush(); 
       } catch (IOException e) { 
        throw new RuntimeException(e); 
       } 
      } 
      return null; 
     } 
    } 
} 
+0

_synchronized (mSocketContainerLock) _ Не удается разрешить mSocketContainerLock –

+0

@GiuseppeCesaranoPecoraInPann вы использовали точно такой же код, я при условии или расчленены внутренние классы в отдельные классы? – nandsito

+0

@ nandsito U're rigth я расчленял внутренние классы, можно сделать эту работу в файле другого класса? –

0

С помощью этого кода я подключиться к чату, так что вы можете использовать его similliary соединиться с тем, что вы хотите

public class SocialConnectionManager extends AsyncTask<Void, Void, Void> { 

    public static final int SQL_STEP_LOGIN = 0; 
    public static final int SQL_STEP_LOGOUT = 1; 
    public static final int SQL_STEP_SEND = 2; 
    public static final int SQL_STEP_UPDATE = 3; 

    final int serverPort = 8080; 
    private String message, channel, userName, serverIp; 
    private int step; 
    private long uniqueId; 
    private Activity activity; 

    public SocialConnectionManager(String serverIp, long uniqueId, int step, String userName, 
            String channel, String message, Activity activity) { 
     this.message = message; 
     this.step = step; 
     this.uniqueId = uniqueId; 
     this.channel = channel; 
     this.userName = userName; 
     this.serverIp = serverIp; 
     this.activity = activity; 
    } 

    @Override 
    protected Void doInBackground(Void... arg0) { 

     Socket socket = null; 

     try { 
      socket = new Socket(serverIp, serverPort); 
      DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream()); 
      switch (step) { 
       case SQL_STEP_LOGIN: 
        dataOut.writeInt(step); 
        dataOut.writeLong(uniqueId); 
        dataOut.writeUTF(channel); 
        dataOut.writeUTF(userName); 
        break; 
       case SQL_STEP_LOGOUT: 
        dataOut.writeInt(step); 
        dataOut.writeLong(uniqueId); 
        dataOut.writeUTF(channel); 
        dataOut.writeUTF(userName); 
        break; 
       case SQL_STEP_SEND: 
        long messageId = createRandomId(); 
        messageIds.add(messageId); 
        dataOut.writeInt(step); 
        dataOut.writeLong(uniqueId); 
        dataOut.writeUTF(channel); 
        dataOut.writeUTF(userName); 
        dataOut.writeUTF(message); 
        dataOut.writeLong(messageId); 
        break; 
       case SQL_STEP_UPDATE: 
        dataOut.writeInt(step); 
        dataOut.writeUTF(message); 
        break; 
      } 
      dataOut.flush(); 

     } catch (UnknownHostException e) { 
      activity.runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        ((MainActivity) activity).showNetworkAlertDialog(context.getString 
          (R.string.social_chat_connection_failed)); 
       } 
      }); 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (socket != null) { 
       try { 
        socket.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     super.onPostExecute(result); 
    } 
} 

private class ReceiveTask extends AsyncTask { 

    final int clientPort = 5050; 

    @Override 
    protected Object doInBackground(Object[] params) { 
     try { 
      serverSocket = new ServerSocket(clientPort); 
      while (true) { 
       final Socket socket = serverSocket.accept(); 
       DataInputStream dataIn = new DataInputStream(socket.getInputStream()); 
       final int step = dataIn.readInt(); 
       final int userCount = dataIn.readInt(); 
       final String message = dataIn.readUTF(); 
       final String userName = dataIn.readUTF(); 
       switch (step) { 
        case SocialConnectionManager.SQL_STEP_LOGIN: 
         if (isLogging) { 
          activity.runOnUiThread(new Runnable() { 
           @Override 
           public void run() { 
            showProgress(false); 
           } 
          }); 
          isLogging = false; 
          isLoggedIn = true; 
         } 
         activity.runOnUiThread(new Runnable() { 
          @Override 
          public void run() { 
           userCountView.setText(Integer.toString(userCount)); 
           addMessage(message, userName, step); 
          } 
         }); 
         break; 
        case SocialConnectionManager.SQL_STEP_LOGOUT: 
         activity.runOnUiThread(new Runnable() { 
          @Override 
          public void run() { 
           addMessage(message, userName, step); 
          } 
         }); 
         break; 
        case SocialConnectionManager.SQL_STEP_SEND: 
         messageId = dataIn.readLong(); 
         activity.runOnUiThread(new Runnable() { 
          @Override 
          public void run() { 
           addMessage(message, userName, step); 
          } 
         }); 
         break; 
       } 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

BroadcastReceiver networkStateReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     String ip = getIpAddress(); 
     if (ip.equals("")) { 
      ((MainActivity) activity).showNetworkAlertDialog(context.getString 
        (R.string.social_chat_connection_lost)); 
     } else if (!deviceIp.equals(ip)) { 
      SocialConnectionManager socialConnectionManager = 
        new SocialConnectionManager(serverIp, 0, 
          SocialConnectionManager.SQL_STEP_UPDATE, null, null, deviceIp, 
          activity); 
      socialConnectionManager.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
     } 
    } 
}; 

}