Android приложение TCP рабочий - PullRequest
0 голосов
/ 09 сентября 2011

Я планирую приложение для Android, которое связывается с программой для ПК через сокет TCP.Приложение будет иметь несколько Активов (макет), каждая из которых представляет отдельное физическое устройство, подключенное к ПК.Я хотел бы иметь сокет TCP, который подключается к серверу ПК, когда приложение сначала открывается, а затем работает в фоновом режиме.Когда у пользователя открыто действие для устройства A, сокет TCP должен непрерывно отправлять запросы хосту о состоянии устройства A, а затем обновлять пользовательский интерфейс самыми последними данными.

Я просматривал различныевозможности для запуска фоновых задач, и я не уверен, какой вариант лучше в этом случае.Должны ли мои операции TCP непрерывно выполняться в потоке?Я понимаю, что Сервис должен использоваться только для неблокирующих операций, и я не могу гарантировать, что сетевые транзакции будут происходить мгновенно (особенно, если соединение с сетью потеряно).

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

1 Ответ

1 голос
/ 09 сентября 2011

Мы создаем приложение для Android, которое взаимодействует с оборудованием через TCP-сокет, прослушивая различные события с устройства, а также взаимодействуя с ним с помощью действий пользователя. Подобно тому, что вы собираетесь делать, в нашем приложении также есть несколько действий, которые получают разные данные в зависимости от контекста действия. Для приложения мы сделали следующий подход:

  • Создайте обработчик ответа и запроса, который отвечает за открытие вывода сокета и входного потока.
  • Мы запустили эти два в отдельном потоке. Обработчик запросов принимает запрос из очереди блокировки, содержащей запрос
  • Каждый запрос идентифицируется своим типом, идентификатором запроса, отметкой времени и обработчиком.
    • Тип идентифицирует контекст запроса (в вашем случае тип устройства)
    • Обработчик использует Android Handler , который отвечает за обработку запроса с определенным идентификатором и типом. В вашем случае у вас будет DeviceAHandler, DeviceBHandler и т. Д., Которые вы будете связывать с определенным идентификатором и типом. При таком подходе ваш обработчик может обрабатывать конкретное обновление пользовательского интерфейса для конкретного устройства
  • Для обработчика ответа у нас есть блокирующий входной поток, который ожидает ответа, после получения ответа мы сопоставляем идентификатор ответа с идентификатором запроса и получаем обработчик, связанный с идентификатором
  • При изменении контекста на конкретное действие мы отправляем запрос с другим типом запроса. В вашем случае, когда вы меняете действие, вы можете использовать onStart для отправки переключателя типа запроса на сервер. Поскольку предыдущие обработчики, которые вы регистрируете, обрабатывают определенный контекст (через тип запроса), они будут игнорировать ответ, если он не совпадает с новым типом запроса.

Обработчик запросов и ответов реализован как AsyncTask, ниже приведена заглушка для ResponseHandler, чтобы вы могли лучше понять, что я написал:


public class ResponseHandler extends AsyncTask {
    boolean isConnectionClosed = false;

    @Override
    protected Integer doInBackground(Void... params) {
        int errorCode = 0;

        try {
            // while not connection is not close
            while(!isConnectionClosed){
                // blocking call from the device/server
                String responseData = getResponse();

                // once you get the data, you publish the progress
                // this would be executed in the UI Thread
                publishProgress(responseData);
            }
        } catch(Exception e) {
            // error handling code that assigns appropriate error code
        }

        return errorCode;

    }

    @Override
    protected void onPostExecute(Integer errorCode) {
        // handle error on UI Thread
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        String responseData = values[0];

        // the response contains the requestId that we need to extract
        int requestId = extractId(responseData);

        // next use the requestId to get the appropriate handler
        Handler uiHandler = getUIHandler(requestId);

        // send the message with data, note that this is just the illustration
        // your data not necessary be jut String
        Message message = uiHandler.obtainMessage();
        message.obj = responseData;
        uiHandler.sendMessage(message);
    }

    /***
     * Stub code for illustration only
     * Get the handler from the Map of requestId map to a Handler that you register from the UI
     * @param requestId Request id that is mapped to a particular handler
     * @return
     */
    private Handler getUIHandler(int requestId) {
        return null;
    }

    /***
     * Stub code for illustration only, parse the response and get the request Id
     * @param responseId
     * @return
     */
    private int extractId(String responseId) {
        return 0;
    }

    /***
     * Stub code for illustration only
     * Call the server to get the TCP data. This is a blocking socket call that wait
     * for the server response
     * @return
     */
    private String getResponse() {
        return null;
    }
}
...