2015-12-22 41 views
5

我有多个活动其中的每一个由不同的URL,不同的HTTP方法等POSTGETPUTDELETE等 有些要求有标题数据得到不同的数据,而一些具有车身,有些人可能兼得。 我正在使用一个具有多个构造函数的AsyncTask类来传递活动中的数据,以便我可以将它们添加到HttpUrlConnection实例中。如何将HttpUrlConnection的逻辑分成多个方法?

我试过这个教程:http://cyriltata.blogspot.in/2013/10/android-re-using-asynctask-class-across.html

但上面的教程使用HttpClientNameValuePair。我用Pair替换了NameValuePair。但是我发现很难使用HttpUrlConnection来实现相同的逻辑,因为我需要为我的请求添加多个POST数据和标头。

但是返回的字符串是空的。我如何正确实施这种情况?

全码:

public class APIAccessTask extends AsyncTask<String,Void,String> { 
URL requestUrl; 
Context context; 
HttpURLConnection urlConnection; 
List<Pair<String,String>> postData, headerData; 
String method; 
int responseCode = HttpURLConnection.HTTP_NOT_FOUND; 


APIAccessTask(Context context, String requestUrl, String method){ 
    this.context = context; 
    this.method = method; 
    try { 
     this.requestUrl = new URL(requestUrl); 
    } 
    catch(Exception ex){ 
     ex.printStackTrace(); 
    } 
} 


APIAccessTask(Context context, String requestUrl, String method, List<Pair<String,String>> postData,){ 
    this(context, requestUrl, method); 
    this.postData = postData; 
} 

APIAccessTask(Context context, String requestUrl, String method, List<Pair<String,String>> postData, 
       List<Pair<String,String>> headerData){ 
    this(context, requestUrl,method,postData); 
    this.headerData = headerData; 
} 

@Override 
protected void onPreExecute() { 
    super.onPreExecute(); 
} 

@Override 
protected String doInBackground(String... params) { 

    setupConnection(); 

    if(method.equals("POST")) 
    { 
     return httpPost(); 
    } 

    if(method.equals("GET")) 
    { 
     return httpGet(); 
    } 

    if(method.equals("PUT")) 
    { 
     return httpPut(); 
    } 

    if(method.equals("DELETE")) 
    { 
     return httpDelete(); 
    } 
    if(method.equals("PATCH")) 
    { 
     return httpPatch(); 
    } 

    return null; 
} 

@Override 
protected void onPostExecute(String result) { 
    Toast.makeText(context,result,Toast.LENGTH_LONG).show(); 
    super.onPostExecute(result); 
} 

void setupConnection(){ 
    try { 
     urlConnection = (HttpURLConnection) requestUrl.openConnection(); 
     urlConnection.setDoOutput(true); 
     urlConnection.setDoInput(true); 
     urlConnection.setChunkedStreamingMode(0); 
     if(headerData != null){ 
      for (Pair pair: headerData) 
      { 
       urlConnection.setRequestProperty(pair.first.toString(), Base64.encodeToString(pair.second.toString().getBytes(),Base64.DEFAULT)); 
      } 
     } 
    } 
    catch(Exception ex) { 
     ex.printStackTrace(); 
    } 

} 

private String httpPost(){ 
    try{ 
     urlConnection.setRequestMethod("POST"); 
    } 
    catch (Exception ex){ 
     ex.printStackTrace(); 

    return stringifyResponse(); 
} 

String httpGet(){ 

    try{ 
     urlConnection.setRequestMethod("GET"); 
    } 
    catch (Exception ex){ 
     ex.printStackTrace(); 
    } 
    return stringifyResponse(); 
} 

String httpPut(){ 

    try{ 
     urlConnection.setRequestMethod("PUT"); 
    } 
    catch (Exception ex){ 
     ex.printStackTrace(); 
    } 
    return stringifyResponse(); 
} 

String httpDelete(){ 
    try{ 
     urlConnection.setRequestMethod("DELETE"); 
    } 
    catch (Exception ex){ 
     ex.printStackTrace(); 
    } 
    return stringifyResponse(); 

} 

String httpPatch(){ 
    try{ 
     urlConnection.setRequestMethod("PATCH"); 
    } 
    catch (Exception ex){ 
     ex.printStackTrace(); 
    } 
    return stringifyResponse(); 

} 

String stringifyResponse() { 

    StringBuilder sb = new StringBuilder(); 
    try { 
     OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); 
     BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); 
     writer.write(getQuery(postData)); 
     writer.flush(); 
     writer.close(); 
     out.close(); 

     urlConnection.connect(); 
     responseCode = urlConnection.getResponseCode(); 
     if (responseCode == 200) { 
      InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); 
      String line = null; 

      while ((line = reader.readLine()) != null) { 
       sb.append(line); 
      } 
     } 

    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
    return sb.toString(); 
} 


private String getQuery(List<Pair<String,String>> params) throws UnsupportedEncodingException{ 
    Uri.Builder builder = null; 
    for (Pair pair : params) 
    { 
     builder = new Uri.Builder() 
       .appendQueryParameter(pair.first.toString(), pair.second.toString()); 
       } 
    return builder.build().getEncodedQuery(); 
} 
} 
+1

您可以在您尝试向请求添加多个POST数据的位置添加代码。 –

+2

不清楚你在问什么。您不需要多个方法来添加多个POST名称 - 值对或标题。 – EJP

+0

IMO,根据您的要求,您可以参考Google Volley的源代码,从[HurlStack.java]的'setConnectionParametersForRequest'开始(https://android.googlesource.com/platform/frameworks/volley/+/master/src/ main/java/com/android/volley/toolbox/HurlStack.java) – BNK

回答

1

IMO,你可以参考我下面的示例代码:

​​

requestBody由使用以下方法:

public static String buildRequestBody(Object content) { 
     String output = null; 
     if ((content instanceof String) || 
       (content instanceof JSONObject) || 
       (content instanceof JSONArray)) { 
      output = content.toString(); 
     } else if (content instanceof Map) { 
      Uri.Builder builder = new Uri.Builder(); 
      HashMap hashMap = (HashMap) content; 
      if (isValid(hashMap)) { 
       Iterator entries = hashMap.entrySet().iterator(); 
       while (entries.hasNext()) { 
        Map.Entry entry = (Map.Entry) entries.next(); 
        builder.appendQueryParameter(entry.getKey().toString(), entry.getValue().toString()); 
        entries.remove(); // avoids a ConcurrentModificationException 
       } 
       output = builder.build().getEncodedQuery(); 
      } 
     } else if (content instanceof byte[]) { 
      try { 
       output = new String((byte[]) content, "UTF-8"); 
      } catch (UnsupportedEncodingException e) { 
       e.printStackTrace(); 
      } 
     } 

     return output; 
    } 
} 

然后,在你的AsyncTask类中,你可以调用:

 String url = "http://......."; 
     HttpURLConnection urlConnection; 
     Map<String, String> stringMap = new HashMap<>();   
     stringMap.put(KEYWORD_USERNAME, "bnk"); 
     stringMap.put(KEYWORD_PASSWORD, "bnk123"); 
     String requestBody = buildRequestBody(stringMap); 
     try { 
      urlConnection = (HttpURLConnection) Utils.makeURLConnection(HTTP_METHOD_POST, url, null, MIME_FORM_URLENCODED, requestBody);    
      if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { 
       // do something... 
      } else { 
       // do something... 
      } 
      ... 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

 String url = "http://......."; 
     HttpURLConnection urlConnection; 
     JSONObject jsonBody;      
     String requestBody; 
     try { 
      jsonBody = new JSONObject(); 
      jsonBody.put("Title", "Android Demo"); 
      jsonBody.put("Author", "BNK"); 
      requestBody = Utils.buildRequestBody(jsonBody); 
      urlConnection = (HttpURLConnection) Utils.makeURLConnection(HTTP_METHOD_POST, url, null, MIME_JSON, requestBody);    
      if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { 
       // do something... 
      } else { 
       // do something... 
      } 
      ... 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
+0

调用connect()方法有点晚了, *发送请求后*。实际上,你根本不需要调用'connect()'。很难看出这是如何回答queston的,无论它是通过“分解多种方法”来表达。 – EJP

+0

@EJP:我同意你关于connect()。关于“破”,如果我正确理解OP的要求,当他通过“GET”,例如,“方法”参数,它是一个GET请求...如果“POST”通过,这是一个POST请求。 – BNK

1

让应用一些概念哎呀这里
有一个类HttpCommunication与单纯将采取发送请求,并从服务器得到响应回来照顾。示例代码是如下

package com.example.sample; 

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.ArrayList; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.client.utils.URLEncodedUtils; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 

public class HttpCommunication { 
    public String makeHttpRequest(String url, HttpMethods method, ArrayList<NameValuePair> requestParams, ArrayList<NameValuePair> postData) throws Exception { 

     InputStream inputStream = null; 
     String response = ""; 
     HttpParams httpParameters = new BasicHttpParams(); 

     /** 
     * Set the timeout in milliseconds until a connection is established. The default value is 
     * zero, that means the timeout is not used. 
     */ 
     int timeoutConnection = 15000; 
     HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); 

     /** 
     * Set the default socket timeout (SO_TIMEOUT) in milliseconds which is the timeout for 
     * waiting for data. 
     */ 
     int timeoutSocket = 15000; 
     HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); 

     DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters); 

     /** 
     * Check for request method 
     */ 
     if (method == HttpMethods.POST) { 
      HttpPost httpPost = new HttpPost(url); 

      if (requestParams != null && requestParams.size() > 0) { 
       httpPost.setEntity(new UrlEncodedFormEntity(requestParams)); 
      } 

      HttpResponse httpResponse = httpClient.execute(httpPost); 
      HttpEntity httpEntity = httpResponse.getEntity(); 
      inputStream = httpEntity.getContent(); 

     } else if (method == HttpMethods.GET) { 
      if (requestParams != null && requestParams.size() > 0) { 
       String paramString = URLEncodedUtils.format(requestParams, "utf-8"); 
       url += "?" + paramString; 
      } 

      HttpGet httpGet = new HttpGet(url); 

      HttpResponse httpResponse = httpClient.execute(httpGet); 
      HttpEntity httpEntity = httpResponse.getEntity(); 
      inputStream = httpEntity.getContent(); 
     } 

     BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); 
     StringBuilder sb = new StringBuilder(); 
     String line = null; 
     while ((line = reader.readLine()) != null) { 
      sb.append(line + "\n"); 
     } 
     inputStream.close(); 
     response = sb.toString(); 

     return response; 
    } 
} 

有一个抽象基类将作为应用程序中的所有底层web服务的模板。 该类将使用上面的HttpCommunication类发送请求。 请求将从AsyncTask发送,因此它是完全异步的。 该类将提供派生类必须重写并提供定义的抽象方法;
1.使用getURL() - 阱格式化请求URL
2. getHttpMethod() - 一个从GET HTTP方法的,POST,PUT,DELETE,PATCH
3. getRequestParams() - 的请求参数(头)如果有的话。
4. getPostParams() - 后的参数,如果有的话。
5. parseResponse(String) - 派生类必须定义此方法来解析接收到的响应。
6. notifyError(int) - 派生类必须给出此方法的定义来处理可能在通信中接收到的错误。

package com.example.sample; 
import java.util.ArrayList; 
import org.apache.http.NameValuePair; 
import android.os.AsyncTask; 
/** 
* This class is an abstract base class for all web services. 
*/ 
public abstract class BaseService { 
    protected abstract String getUrl(); 
    protected abstract HttpMethods getHttpMethod(); 
    protected abstract ArrayList<NameValuePair> getRequestParams(); 
    protected abstract ArrayList<NameValuePair> getPostParams(); 
    protected abstract void parseResponse(String response); 
    protected abstract void notifyError(int errorCode); 

    public void send() { 
     SendRequestTask sendRequestTask = new SendRequestTask(); 
     sendRequestTask.execute(); 
    } 

    private class SendRequestTask extends AsyncTask< Void, Void, Integer > { 
     @Override 
     protected Integer doInBackground(Void... params) { 
      try { 
       String url = getUrl(); 
       HttpMethods method = getHttpMethod(); 
       ArrayList<NameValuePair> httpParams = getRequestParams(); 
       ArrayList<NameValuePair> postParams = getPostParams(); 

       HttpCommunication httpCommunication = new HttpCommunication(); 
       String response = httpCommunication.makeHttpRequest(url, method, httpParams, postParams); 

       parseResponse(response); 
      } catch (Exception ex) { 
       ex.printStackTrace(); 
       notifyError(CommunicationError.ERROR_COMMUNICATION); 
      } 
      return 0; 
     } 
    } 
} 

下面是其中从上方类来源的样​​品的web服务类的代码;

package com.example.sample; 
import java.util.ArrayList; 
import org.apache.http.NameValuePair; 
import org.apache.http.message.BasicNameValuePair; 
/** 
* This is a web service class to login. 
*/ 
public class SignIn extends BaseService { 
    private final String _emailId; 
    private final String _password; 
    private final String _signinUrl = "http://www.example.com/login.php"; 

    public SignIn(String userName, String password) { 
     _emailId = userName; 
     _password = null; 
    } 

    @Override 
    protected String getUrl() { 
     return _signinUrl; 
    } 

    @Override 
    protected ArrayList<NameValuePair> getRequestParams() { 
     ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(); 
     params.add(new BasicNameValuePair("header1", "header1")); 
     params.add(new BasicNameValuePair("header2", "header2")); 
     return params; 
    } 

    @Override 
    protected ArrayList<NameValuePair> getPostParams() { 
     ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(); 
     params.add(new BasicNameValuePair("email", _emailId)); 
     params.add(new BasicNameValuePair("password", _password)); 
     return params; 
    } 

    @Override 
    protected HttpMethods getHttpMethod() { 
     return HttpMethods.POST; 
    } 

    @Override 
    protected void parseResponse(String response) { 
     // Parse the response here 
    } 

    @Override 
    protected void notifyError(int errorCode) { 
     // Notify error to application 
    } 
} 

这里是您如何使用SignIn webservice;

SignIn signIn = new SignIn("[email protected]", "abc123"); 
signIn.send(); 

请修改您的HttpCommunication类如下。

package com.example.sample; 

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.util.ArrayList; 

import org.apache.http.NameValuePair; 

public class HttpCommunication { 
    private final int CONNECTION_TIMEOUT = 10 * 1000; 

    /** 
    * Default Constructor 
    */ 
    public HttpCommunication() { 

    } 

    public String makeHttpRequest(String strUrl, HttpMethods method, ArrayList<NameValuePair> requestParams, ArrayList<NameValuePair> postData) throws Exception { 

     HttpURLConnection connection = null; 
     InputStream inputStream = null; 
     URL url = null; 
     String response = null; 
     try { 
      url = new URL(strUrl); 
      connection = (HttpURLConnection) url.openConnection(); 
      connection.setConnectTimeout(CONNECTION_TIMEOUT); 
      connection.setReadTimeout(CONNECTION_TIMEOUT); 

      if (requestParams != null && requestParams.size() > 0) { 
       for (NameValuePair pair : requestParams) { 
        connection.setRequestProperty(pair.getName(), pair.getValue()); 
       } 
      } 

      connection.setDoInput(true); 
      connection.connect(); 
      if (method == HttpMethods.POST) { 
       OutputStream os = connection.getOutputStream(); 
       // Convert post data to string and then write it to outputstream. 
       String postDataStr = "test"; 
       os.write(postDataStr.getBytes()); 
       os.close(); 
      } 

      inputStream = connection.getInputStream(); 

      if (inputStream != null) { 
       BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); 
       StringBuilder sb = new StringBuilder(); 
       String line = null; 
       while ((line = reader.readLine()) != null) { 
        sb.append(line + "\n"); 
       } 
       response = sb.toString(); 
       inputStream.close(); 
      } 
      connection.disconnect(); 
     } catch (Exception e) { 
      if (connection != null) { 
       connection.disconnect(); 
      } 
     } 

     return response; 
    } 
} 
+0

我知道这可以通过Apache'HttpClient'完成。从API22开始已弃用。 如果您可以使用'HttpUrlConnection'发布代码,它会很有用。 –

+0

请参考修改后的HttpCommunication类。你不需要改变任何其他课程。 – abidfs