Android app TCP worker
I am planning out an Android app that communicates with a PC program via a TCP Socket. The app will have several Activities(layout) each of which represent a different physical device which is connected to the PC. I would like to have a TCP socket that connects to 开发者_如何学运维the PC server when the app first opens and then runs in the background. When the user has the Activity for Device-A open the TCP socket should continually send requests to the host for Device-A status and then update the UI with the most recent data.
I have been looking at the different possibilities for running background tasks and I am not sure which option is best in this case. Should my TCP ops be continuously running on a Thread? I understand that a Service should only be used for non-blocking operations and I cannot guarantee that network transactions will be instantaneously (especially if connection to the network is lost).
If I were to run the communication in a thread what is the best way to alert the UI that new data has arrived. Also, when the user switches to a different activity what is the best way to alert the thread to start requesting information about a different device?
We are building an Android app that is communicating with a hardware via TCP socket listening to various events from the device as well as communicating with it via user's actions. Similar to what you are about to do, our app has also several Activities that are getting different data based on the context of the activity. For the app, we have done the following approach:
- Create a Response and Request Handler that is responsible for opening the socket output and inputstream.
- We ran these two on its own Thread. The Request Handler is taking the request from a blocking queue that contains the request
- Each Request is identified with its type, request id, timestamp and a Handler.
- The type identifies the context of the request (in your case, the device type)
- A Handler is using Android Handler that is responsible for handling a request with specific id and type. In your case you will have DeviceAHandler, DeviceBHandler etc, that you will associate with specific id and type. With this approach, your Handler can handle a specific UI update for specific device
- For the Response Handler, we have a blocking inputstream that waits for the response, once a response is received, we match the response id to the request id and get the Handler that is associated with the id
- Upon changing context to a specific activity, we are sending request with different request type. In your case, whenever you change the Activity, you can use
onStart
to send a request type switch to the server. Since previous handlers that you register handle specific context (through request type), they will ignore the response if it doesn't match with the new request type.
Both Request and Response Handler are implemented as AsyncTask, below are the stub for the ResponseHandler so that you could understand better what I wrote :
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;
}
}
精彩评论