Android
HttpURLConnection
Ricerca…
Sintassi
- abstract void disconnect ()
- abstract booleano usingProxy ()
- static boolean getFollowRedirects ()
- static void setFollowRedirects (set booleano)
- String getHeaderField (int n)
- String getHeaderFieldKey (int n)
- String getRequestMethod ()
- String getResponseMessage ()
- int getResponseCode ()
- long getHeaderFieldDate (String name, long Default)
- boolean getInstanceFollowRedirects ()
- Autorizzazione getPermission ()
- InputStream getErrorStream ()
- void setChunkedStreamingMode (int chunklen)
- void setFixedLengthStreamingMode (int contentLength)
- void setFixedLengthStreamingMode (long contentLength)
- void setInstanceFollowRedirects (boolean followRedirects)
- void setRequestMethod (metodo String)
Osservazioni
HttpURLConnection
è il client HTTP standard per Android, utilizzato per inviare e ricevere dati sul web. È un'implementazione concreta di URLConnection per HTTP (RFC 2616).
Creazione di un HttpURLConnection
Per creare un nuovo client HTTP Android HttpURLConnection
, chiama openConnection()
su un'istanza URL. Poiché openConnection()
restituisce un URLConnection
, è necessario eseguire il cast esplicito del valore restituito.
URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// do something with the connection
Se stai creando un nuovo URL
, devi anche gestire le eccezioni associate all'analisi degli URL.
try {
URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// do something with the connection
} catch (MalformedURLException e) {
e.printStackTrace();
}
Una volta che il corpo della risposta è stato letto e la connessione non è più necessaria, la connessione deve essere chiusa chiamando disconnect()
.
Ecco un esempio:
URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// do something with the connection
} finally {
connection.disconnect();
}
Invio di una richiesta GET HTTP
URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
// read the input stream
// in this case, I simply read the first line of the stream
String line = br.readLine();
Log.d("HTTP-GET", line);
} finally {
connection.disconnect();
}
Si prega di notare che le eccezioni non sono gestite nell'esempio sopra. Un esempio completo, inclusa la gestione di un'eccezione (banale), potrebbe essere:
URL url;
HttpURLConnection connection = null;
try {
url = new URL("http://example.com");
connection = (HttpURLConnection) url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
// read the input stream
// in this case, I simply read the first line of the stream
String line = br.readLine();
Log.d("HTTP-GET", line);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
Lettura del corpo di una richiesta GET HTTP
URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
// use a string builder to bufferize the response body
// read from the input strea.
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append('\n');
}
// use the string builder directly,
// or convert it into a String
String body = sb.toString();
Log.d("HTTP-GET", body);
} finally {
connection.disconnect();
}
Si prega di notare che le eccezioni non sono gestite nell'esempio sopra.
Utilizzare HttpURLConnection per multipart / form-data
Crea una classe personalizzata per chiamare la richiesta HttpURLConnection multipart / form-data
MultipartUtility.java
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer;
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
*
* @param requestURL
* @param charset
* @throws IOException
*/
public MultipartUtility(String requestURL, String charset)
throws IOException {
this.charset = charset;
// creates a unique boundary based on time stamp
boundary = "===" + System.currentTimeMillis() + "===";
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
}
/**
* Adds a form field to the request
*
* @param name field name
* @param value field value
*/
public void addFormField(String name, String value) {
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
.append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=" + charset).append(
LINE_FEED);
writer.append(LINE_FEED);
writer.append(value).append(LINE_FEED);
writer.flush();
}
/**
* Adds a upload file section to the request
*
* @param fieldName name attribute in <input type="file" name="..." />
* @param uploadFile a File to be uploaded
* @throws IOException
*/
public void addFilePart(String fieldName, File uploadFile)
throws IOException {
String fileName = uploadFile.getName();
writer.append("--" + boundary).append(LINE_FEED);
writer.append(
"Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
writer.append(
"Content-Type: "
+ URLConnection.guessContentTypeFromName(fileName))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
}
/**
* Adds a header field to the request.
*
* @param name - name of the header field
* @param value - value of the header field
*/
public void addHeaderField(String name, String value) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
}
/**
* Completes the request and receives response from the server.
*
* @return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* @throws IOException
*/
public List<String> finish() throws IOException {
List<String> response = new ArrayList<String>();
writer.append(LINE_FEED).flush();
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close();
// checks server's status code first
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
httpConn.disconnect();
} else {
throw new IOException("Server returned non-OK status: " + status);
}
return response;
}
}
Usalo (modo asincrono)
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
// In your case you are not adding form data so ignore this
/*This is to add parameter values */
for (int i = 0; i < myFormDataArray.size(); i++) {
multipart.addFormField(myFormDataArray.get(i).getParamName(),
myFormDataArray.get(i).getParamValue());
}
//add your file here.
/*This is to add file content*/
for (int i = 0; i < myFileArray.size(); i++) {
multipart.addFilePart(myFileArray.getParamName(),
new File(myFileArray.getFileName()));
}
List<String> response = multipart.finish();
Debug.e(TAG, "SERVER REPLIED:");
for (String line : response) {
Debug.e(TAG, "Upload Files Response:::" + line);
// get your server response here.
responseString = line;
}
Invio di una richiesta POST HTTP con parametri
Utilizzare una HashMap per memorizzare i parametri che devono essere inviati al server tramite i parametri POST:
HashMap<String, String> params;
Una volta popolato il params
HashMap, crea lo StringBuilder che verrà utilizzato per inviarlo al server:
StringBuilder sbParams = new StringBuilder();
int i = 0;
for (String key : params.keySet()) {
try {
if (i != 0){
sbParams.append("&");
}
sbParams.append(key).append("=")
.append(URLEncoder.encode(params.get(key), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
i++;
}
Quindi, crea HttpURLConnection, apri la connessione e invia i parametri POST:
try{
String url = "http://www.example.com/test.php";
URL urlObj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.connect();
String paramsString = sbParams.toString();
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(paramsString);
wr.flush();
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
Quindi ricevi il risultato che il server restituisce:
try {
InputStream in = new BufferedInputStream(conn.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
Log.d("test", "result from server: " + result.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();
}
}
Carica (POST) file usando HttpURLConnection
Molto spesso è necessario inviare / caricare un file su un server remoto, ad esempio un'immagine, video, audio o un backup del database dell'applicazione su un server remoto privato. Supponendo che il server si aspetti una richiesta POST con il contenuto, ecco un semplice esempio di come completare questa attività in Android.
I caricamenti dei file vengono inviati utilizzando le richieste POST multipart/form-data
. È molto facile da implementare:
URL url = new URL(postTarget);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
String auth = "Bearer " + oauthToken;
connection.setRequestProperty("Authorization", basicAuth);
String boundary = UUID.randomUUID().toString();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream request = new DataOutputStream(uc.getOutputStream());
request.writeBytes("--" + boundary + "\r\n");
request.writeBytes("Content-Disposition: form-data; name=\"description\"\r\n\r\n");
request.writeBytes(fileDescription + "\r\n");
request.writeBytes("--" + boundary + "\r\n");
request.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.fileName + "\"\r\n\r\n");
request.write(FileUtils.readFileToByteArray(file));
request.writeBytes("\r\n");
request.writeBytes("--" + boundary + "--\r\n");
request.flush();
int respCode = connection.getResponseCode();
switch(respCode) {
case 200:
//all went ok - read response
...
break;
case 301:
case 302:
case 307:
//handle redirect - for example, re-post to the new location
...
break;
...
default:
//do something sensible
}
Naturalmente, le eccezioni dovranno essere catturate o dichiarate come gettate. Un paio di punti da notare su questo codice:
-
postTarget
è l'URL di destinazione del POST;oauthToken
è il token di autenticazione;fileDescription
è la descrizione del file, che viene inviato come valore delladescription
del campo;file
è il file da inviare - è di tipojava.io.File
- se hai il percorso del file, puoi usare invece ilnew File(filePath)
. - Imposta l'intestazione
Authorization
per un'autenticazione oAuth - Usa Apache Common
FileUtil
per leggere il file in un array di byte - se hai già il contenuto del file in un array di byte o in qualche altro modo in memoria, allora non c'è bisogno di leggerlo.
Una classe HttpURLConnection multiuso per gestire tutti i tipi di richieste HTTP
La seguente classe può essere utilizzata come singola classe in grado di gestire GET
, POST
, PUT
, PATCH
e altre richieste:
class APIResponseObject{
int responseCode;
String response;
APIResponseObject(int responseCode,String response)
{
this.responseCode = responseCode;
this.response = response;
}
}
public class APIAccessTask extends AsyncTask<String,Void,APIResponseObject> {
URL requestUrl;
Context context;
HttpURLConnection urlConnection;
List<Pair<String,String>> postData, headerData;
String method;
int responseCode = HttpURLConnection.HTTP_OK;
interface OnCompleteListener{
void onComplete(APIResponseObject result);
}
public OnCompleteListener delegate = null;
APIAccessTask(Context context, String requestUrl, String method, OnCompleteListener delegate){
this.context = context;
this.delegate = delegate;
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, OnCompleteListener delegate){
this(context, requestUrl, method, delegate);
this.postData = postData;
}
APIAccessTask(Context context, String requestUrl, String method, List<Pair<String,String>> postData,
List<Pair<String,String>> headerData, OnCompleteListener delegate ){
this(context, requestUrl,method,postData,delegate);
this.headerData = headerData;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected APIResponseObject doInBackground(String... params) {
Log.d("debug", "url = "+ requestUrl);
try {
urlConnection = (HttpURLConnection) requestUrl.openConnection();
if(headerData != null) {
for (Pair pair : headerData) {
urlConnection.setRequestProperty(pair.first.toString(),pair.second.toString());
}
}
urlConnection.setDoInput(true);
urlConnection.setChunkedStreamingMode(0);
urlConnection.setRequestMethod(method);
urlConnection.connect();
StringBuilder sb = new StringBuilder();
if(!(method.equals("GET"))) {
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
writer.write(getPostDataString(postData));
writer.flush();
writer.close();
out.close();
}
urlConnection.connect();
responseCode = urlConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
return new APIResponseObject(responseCode, sb.toString());
}
catch(Exception ex){
ex.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(APIResponseObject result) {
delegate.onComplete(result);
super.onPostExecute(result);
}
private String getPostDataString(List<Pair<String, String>> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for(Pair<String,String> pair : params){
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(pair.first,"UTF-8"));
result.append("=");
result.append(URLEncoder.encode(pair.second, "UTF-8"));
}
return result.toString();
}
}
uso
Utilizzare uno dei costruttori dati della classe a seconda se è necessario inviare dati POST
o eventuali intestazioni extra.
Il metodo onComplete()
verrà chiamato quando il recupero dei dati è completo. I dati vengono restituiti come oggetto della classe APIResponseObject
, che ha un codice di stato che indica il codice di stato HTTP della richiesta e una stringa contenente la risposta. È possibile analizzare questa risposta nella classe, ad esempio XML o JSON.
Chiama execute()
sull'oggetto della classe per eseguire la richiesta, come mostrato nell'esempio seguente:
class MainClass {
String url = "https://example.com./api/v1/ex";
String method = "POST";
List<Pair<String,String>> postData = new ArrayList<>();
postData.add(new Pair<>("email","whatever");
postData.add(new Pair<>("password", "whatever");
new APIAccessTask(MainActivity.this, url, method, postData,
new APIAccessTask.OnCompleteListener() {
@Override
public void onComplete(APIResponseObject result) {
if (result.responseCode == HttpURLConnection.HTTP_OK) {
String str = result.response;
// Do your XML/JSON parsing here
}
}
}).execute();
}