与长轮询的Android聊天

时间:2017-04-11 16:10:49

标签: java php android

我在Android应用中使用长轮询实现聊天应用程序时遇到问题。搜索新邮件工作正常,它在HttpUrlConnection的异步任务中运行。问题在于发送消息。我还使用HttpUrlConnection的另一个异步任务,但根据我打印的日志,只有在搜索新消息完成后,即在30秒的长轮询之后才会发送消息。 这是我正在使用的异步尝试:

HttpPost.java

package com.roscosoft.taxifast;

import android.os.AsyncTask;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

/**
 * Created by titin on 7/12/16.
 */

public class HttpPost extends AsyncTask<Void, Void, Boolean> {
Exception error;

public interface HttpPostInterface {
    void termino(JSONObject obj);
    void cancelo(String error);
}


public static String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
    StringBuilder result = new StringBuilder();
    boolean first = true;
    for(Map.Entry<String, String> entry : params.entrySet()){
        if (first)
            first = false;
        else
            result.append("&");

        result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
        result.append("=");
        result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
    }

    return result.toString();
}

private StringBuilder response;
private String postDataString;
private String url;
private HttpPostInterface delegate;
private int timeout;

HttpPost(String urlx, String postDataStringx, HttpPostInterface del) {
    url = urlx;
    postDataString = postDataStringx;
    delegate = del;
    timeout = 30000;
}
HttpPost(String urlx, String postDataStringx, HttpPostInterface del, int timeoutx) {
    url = urlx;
    postDataString = postDataStringx;
    delegate = del;
    timeout = timeoutx;
}


@Override
protected Boolean doInBackground(Void... params) {
    response = new StringBuilder();
    URL urlc = null;
    HttpURLConnection con = null;
    try{
        urlc = new URL(url);
    }catch (MalformedURLException e){
        Log.i("rosco", e.getMessage());
        error = e;
        return false;
    }
    try {
        con = (HttpURLConnection)urlc.openConnection();
        con.setReadTimeout(timeout);
        con.setConnectTimeout(timeout);
        con.setRequestMethod("POST");
        con.setDoInput(true);
        con.setDoOutput(true);

        OutputStream os = con.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
        writer.write(postDataString);

        writer.flush();
        writer.close();
        os.close();

        int responseCode = con.getResponseCode();
        if (responseCode == HttpsURLConnection.HTTP_OK){
            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            while ((line = br.readLine()) != null){
                response.append(line);
            }
        }else{
            error = new Exception("Error:"+responseCode);
            return false;
        }
    } catch (Exception e) {
        Log.i("rosco", "Hubo un error al hacer el request:"+e.getMessage());
        error = e;
        return false;
    }finally {
        con.disconnect();
    }
    return true;
}

@Override
protected void onPostExecute(final Boolean success) {

    if (success) {
        try{
            if (response.toString().length() == 0){
                if(delegate != null) delegate.cancelo("No hay respuesta del servidor");
            }else{
                //Log.i("rosco", response.toString()); // solo en desarrollo
            }
            JSONObject obj = new JSONObject(response.toString());
            if(delegate != null) delegate.termino(obj);
        }catch (JSONException e){
            Log.i("rosco", "Json malformado:"+e.getMessage()+":\n"+response.toString());
            if(delegate != null) delegate.cancelo(response.toString());
        }
    } else {
        if(delegate != null) delegate.cancelo(error.getMessage());
    }
}

@Override
protected void onCancelled() {
    if(delegate != null) {
        if (error == null)
            delegate.cancelo("Se cancelo el request");
        else
            delegate.cancelo(error.getMessage());
    }
}
}

Web服务是用PHP制作的,服务器可能会等待第一个连接完成以接受发送消息&#39;连接? 如果是这样,你知道如何解决它吗? 非常感谢提前。

2 个答案:

答案 0 :(得分:1)

您需要使用THREAD_POOL_EXECUTOR来执行AsyncTask。默认实现使用在单个线程上运行的串行执行程序

new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

答案 1 :(得分:0)

所有AsyncTasks都在单线程中执行序列。虽然第一个AsyncTask没有完成,但第二个任务将无法启动。我(和很多开发人员)不建议使用AsyncTask。 替代方案:来自java.util.concurrent的Java线程,Rx,Executors等。 或者使用Square的Retrofit库来执行异步http请求。