我有多个活动,每个活动都会从不同的网址和不同的HTTP方法获取不同的数据,例如POST
,GET
,PUT
,DELETE
等。
有些请求有标题数据,有些请求有Body,有些可能有两个。
我正在使用带有多个构造函数的单个AsyncTask
类来传递活动中的数据,以便我可以将它们添加到HttpUrlConnection
实例。
我尝试了本教程:http://cyriltata.blogspot.in/2013/10/android-re-using-asynctask-class-across.html。
但上述教程使用HttpClient
和NameValuePair
。我将NameValuePair
替换为Pair
。但我发现很难使用HttpUrlConnection
实现相同的逻辑,因为我需要在我的请求中添加多个POST
数据和标题。
但返回的String是空的。如何正确实施此方案?
完整代码:
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();
}
}
答案 0 :(得分:1)
IMO,您可以参考我的以下示例代码:
/**
* HTTP request using HttpURLConnection
*
* @param method
* @param address
* @param header
* @param mimeType
* @param requestBody
* @return
* @throws Exception
*/
public static URLConnection makeURLConnection(String method, String address, String header, String mimeType, String requestBody) throws Exception {
URL url = new URL(address);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(!method.equals(HTTP_METHOD_GET));
urlConnection.setRequestMethod(method);
if (isValid(header)) { // let's assume only one header here
urlConnection.setRequestProperty(KEYWORD_HEADER_1, header);
}
if (isValid(requestBody) && isValid(mimeType) && !method.equals(HTTP_METHOD_GET)) {
urlConnection.setRequestProperty(KEYWORD_CONTENT_TYPE, mimeType);
OutputStream outputStream = new BufferedOutputStream(urlConnection.getOutputStream());
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8");
writer.write(requestBody);
writer.flush();
writer.close();
outputStream.close();
}
urlConnection.connect();
return urlConnection;
}
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();
}
答案 1 :(得分:1)
让我们在这里应用一些oops概念 有一个类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() - 格式正确的请求网址
2. getHttpMethod() - 来自GET,POST,PUT,DELETE,PATCH的HTTP方法之一
3. getRequestParams() - 请求参数(标题),如果有的话
4. getPostParams() - post params if。如果有的话
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;
}
}
}
以下是从上面的类派生的示例webservice类的代码;
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("abic@gmail.com", "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;
}
}