2015-12-22 64 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

相關問題