【问题标题】:Android app TCP workerAndroid 应用 TCP 工作者
【发布时间】:2011-11-13 18:03:00
【问题描述】:

我正在计划开发一个通过 TCP 套接字与 PC 程序通信的 Android 应用程序。该应用程序将有几个活动(布局),每个活动代表连接到 PC 的不同物理设备。我想要一个 TCP 套接字,当应用程序首次打开然后在后台运行时连接到 PC 服务器。当用户打开 Device-A 的 Activity 时,TCP 套接字应不断向主机发送请求以获取 Device-A 的状态,然后使用最新数据更新 UI。

我一直在研究运行后台任务的不同可能性,但我不确定在这种情况下哪个选项最好。我的 TCP 操作是否应该在线程上持续运行?我了解 Service 只能用于非阻塞操作,并且我不能保证网络事务会立即进行(尤其是在与网络的连接丢失的情况下)。

如果我要在线程中运行通信,那么提醒 UI 新数据已到达的最佳方式是什么。此外,当用户切换到不同的活动时,提醒线程开始请求有关不同设备的信息的最佳方法是什么?

【问题讨论】:

    标签: android multithreading sockets tcp


    【解决方案1】:

    我们正在构建一个 Android 应用,它通过 TCP 套接字与硬件通信,监听来自设备的各种事件,并通过用户的操作与硬件通信。与您将要做的类似,我们的应用程序也有几个活动,它们根据活动的上下文获取不同的数据。对于应用,我们做了以下做法:

    • 创建负责打开套接字输出和输入流的响应和请求处理程序。
    • 我们在自己的线程上运行这两个。请求处理程序正在从包含请求的阻塞队列中获取请求
    • 每个请求都通过其类型、请求 ID、时间戳和处理程序进行标识。
      • 类型标识请求的上下文(在您的情况下是设备类型)
      • 处理程序正在使用Android Handler,它负责处理具有特定 ID 和类型的请求。在您的情况下,您将拥有 DeviceAHandler、DeviceBHandler 等,您将与特定的 id 和类型相关联。通过这种方法,您的 Handler 可以处理特定设备的特定 UI 更新
    • 对于响应处理程序,我们有一个等待响应的阻塞输入流,一旦收到响应,我们将响应 id 与请求 id 匹配,并获取与 id 关联的 Handler
    • 将上下文更改为特定活动后,我们将发送具有不同请求类型的请求。在您的情况下,每当您更改活动时,您都可以使用onStart 向服务器发送请求类型切换。由于您注册的先前处理程序处理特定上下文(通过请求类型),因此如果响应与新请求类型不匹配,它们将忽略响应。

    Request 和 Response Handler 都实现为 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;
        }
    }
    

    【讨论】:

    • 谢谢你的例子。这真的很有帮助。问题,您在哪里创建 TCP 套接字以便所有活动都可以访问它?上面的类应该被编码为单例吗?
    • 我有一个包含请求和响应处理程序的类,该类是一个可以从其他活动访问的单例
    • 啊好的。那就是我缺少的那部分。这一切都非常有帮助。我用 C# 编写了很多程序,但这是我的第一个 java/android 工作!
    猜你喜欢
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 2011-02-25
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多