Invia una richiesta HTTP con Android


352

Ho cercato ovunque ma non sono riuscito a trovare la mia risposta, c'è un modo per fare una semplice richiesta HTTP? Voglio richiedere una pagina / script PHP su uno dei miei siti Web, ma non voglio mostrare la pagina web.

Se possibile, voglio persino farlo in background (in un BroadcastReceiver)


Risposte:


477

AGGIORNARE

Questa è una risposta molto vecchia. Sicuramente non consiglierò più il client di Apache. Utilizza invece:

Risposta originale

Prima di tutto, richiedi un'autorizzazione per accedere alla rete, aggiungi quanto segue al tuo manifest:

<uses-permission android:name="android.permission.INTERNET" />

Quindi il modo più semplice è usare il client http di Apache in bundle con Android:

    HttpClient httpclient = new DefaultHttpClient();
    HttpResponse response = httpclient.execute(new HttpGet(URL));
    StatusLine statusLine = response.getStatusLine();
    if(statusLine.getStatusCode() == HttpStatus.SC_OK){
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        response.getEntity().writeTo(out);
        String responseString = out.toString();
        out.close();
        //..more logic
    } else{
        //Closes the connection.
        response.getEntity().getContent().close();
        throw new IOException(statusLine.getReasonPhrase());
    }

Se vuoi che funzioni su thread separato, ti consiglio di estendere AsyncTask:

class RequestTask extends AsyncTask<String, String, String>{

    @Override
    protected String doInBackground(String... uri) {
        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response;
        String responseString = null;
        try {
            response = httpclient.execute(new HttpGet(uri[0]));
            StatusLine statusLine = response.getStatusLine();
            if(statusLine.getStatusCode() == HttpStatus.SC_OK){
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                responseString = out.toString();
                out.close();
            } else{
                //Closes the connection.
                response.getEntity().getContent().close();
                throw new IOException(statusLine.getReasonPhrase());
            }
        } catch (ClientProtocolException e) {
            //TODO Handle problems..
        } catch (IOException e) {
            //TODO Handle problems..
        }
        return responseString;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        //Do anything with response..
    }
}

È quindi possibile effettuare una richiesta:

   new RequestTask().execute("http://stackoverflow.com");

11
Ecco un articolo dal blog ufficiale degli sviluppatori Android su AsyncTask: android-developers.blogspot.com/2010/07/…
Austyn Mahoney,

77
per il pan di zenzero o superiore si consiglia effettivamente di utilizzare HttpURLConnection tramite la libreria apache, consultare android-developers.blogspot.com/2011/09/… . È meno faticoso per la batteria e ha prestazioni migliori
Marty,

8
responseString = out.toString () deve essere prima della chiamata out.close (). In realtà, probabilmente dovresti avere out.close () in un blocco finally. Ma nel complesso, risposta molto utile (+1), grazie!
dcp,

9
A partire da Honeycomb (SDK 11) l'approccio asincrono è la strada da percorrere. Una NetworkOnMainThreadException viene generata quando si tenta di eseguire una richiesta HTTP dal thread principale.
msrxthr,

2
Questa risposta è abbastanza eccellente. Ma consiglierei di non usare AsyncTasks per il networking. Possono creare perdite di memoria molto facilmente (e in realtà l'esempio fornito perde) e non forniscono tutte le funzionalità che ci si può aspettare dalle richieste di rete. Prendi in considerazione l'utilizzo di RoboSpice per questo tipo di attività in background: github.com/octo-online/robospice
Snicolas

67

a meno che tu non abbia un motivo esplicito per scegliere Apache HttpClient, dovresti preferire java.net.URLConnection. puoi trovare molti esempi di come usarlo sul web.

abbiamo anche migliorato la documentazione di Android dal tuo post originale: http://developer.android.com/reference/java/net/HttpURLConnection.html

e abbiamo parlato dei compromessi sul blog ufficiale: http://android-developers.blogspot.com/2011/09/androids-http-clients.html


13
Perché l'uso di Apache HttpClient non è raccomandato?
Ted,

4
Un mio co-cospiratore ha approfondito il tema
Elliott Hughes il

@ElliottHughes: sono d'accordo al 100%. Non si può negare che Apache httpclient offra metodi semplici e una visione più astratta del protocollo, ma la connessione url nativa di java non è in alcun modo meno utile. Con un po 'di pratica, è facile da usare come httpclient ed è molto più portatile
Nitin Bansal

1
In realtà, se dai un'occhiata al video Google I / O 2010 - Applicazioni client Android REST ( youtube.com/watch?v=xHXn3Kg2IQE 57min21sec) vedresti che Apache HttpClient è il più raccomandato. Cito Virgil Dobjanschi (un ingegnere del software su Google che lavora su Android Application Group) "Vorrei semplicemente consigliarti di utilizzare il client Apache HTTP, poiché ha un'implementazione più solida. Il tipo di connessione URL della transazione HTTP non è il più efficiente implementazione. E il modo in cui termina le connessioni a volte può avere un effetto negativo sulla rete. "
Alan,

46

Nota: il client HTTP Apache in bundle con Android è ora obsoleto a favore di HttpURLConnection . Per ulteriori dettagli, consultare il Blog degli sviluppatori Android .

Aggiungi <uses-permission android:name="android.permission.INTERNET" />al tuo manifest.

Dovresti quindi recuperare una pagina Web in questo modo:

URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
     readStream(in);
}
finally {
     urlConnection.disconnect();
}

Suggerisco anche di eseguirlo su un thread separato:

class RequestTask extends AsyncTask<String, String, String>{

@Override
protected String doInBackground(String... uri) {
    String responseString = null;
    try {
        URL url = new URL(myurl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        if(conn.getResponseCode() == HttpsURLConnection.HTTP_OK){
            // Do normal input or output stream reading
        }
        else {
            response = "FAILED"; // See documentation for more info on response handling
        }
    } catch (ClientProtocolException e) {
        //TODO Handle problems..
    } catch (IOException e) {
        //TODO Handle problems..
    }
    return responseString;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    //Do anything with response..
}
}

Consultare la documentazione per ulteriori informazioni sulla gestione delle risposte e richieste POST.


1
@Semmix In che modo? La domanda richiedeva "una semplice richiesta HTTP" e il mio codice fa esattamente questo.
Kevin

1
Ho capito che il tuo primo blocco di codice è stato copiato e incollato dai documenti Android, ma l'uomo è quell'immondizia campione / documento. readStreamnon è nemmeno definito.
Eugene K,

@EugeneK Lo sono, ma questo è probabilmente il modo più semplice per rispondere a questa domanda. Fare correttamente una richiesta HTTP in Android implicherebbe spiegare Retrofit e OkHttp. Penso che ciò confonderebbe i principianti più che semplicemente distribuire uno snippet che tecnicamente farà una semplice richiesta HTTP, anche se costruita male.
Kevin

12

Il modo più semplice è usare la lib Android chiamata Volley

Volley offre i seguenti vantaggi:

Pianificazione automatica delle richieste di rete. Più connessioni di rete simultanee . Memorizzazione nella cache di risposta di disco e memoria con coerenza cache HTTP standard. Supporto per priorità delle richieste. API di richiesta di cancellazione. È possibile annullare una singola richiesta oppure è possibile impostare blocchi o ambiti di richieste da annullare. Facilità di personalizzazione, ad esempio, per riprovare e backoff. Ordinamento forte che semplifica la corretta compilazione dell'interfaccia utente con i dati recuperati in modo asincrono dalla rete. Strumenti di debug e tracciabilità.

Puoi inviare una richiesta http / https semplice come questa:

        // Instantiate the RequestQueue.
        RequestQueue queue = Volley.newRequestQueue(this);
        String url ="http://www.yourapi.com";
        JsonObjectRequest request = new JsonObjectRequest(url, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    if (null != response) {
                         try {
                             //handle your response
                         } catch (JSONException e) {
                             e.printStackTrace();
                         }
                    }
                }
            }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        queue.add(request);

In questo caso, non è necessario considerare "l'esecuzione in background" o "l'utilizzo della cache" in quanto tutti questi sono già stati eseguiti da Volley.


6
private String getToServer(String service) throws IOException {
    HttpGet httpget = new HttpGet(service);
    ResponseHandler<String> responseHandler = new BasicResponseHandler();
    return new DefaultHttpClient().execute(httpget, responseHandler);

}

Saluti


4

Con una discussione:

private class LoadingThread extends Thread {
    Handler handler;

    LoadingThread(Handler h) {
        handler = h;
    }
    @Override
    public void run() {
        Message m = handler.obtainMessage();
        try {
            BufferedReader in = 
                new BufferedReader(new InputStreamReader(url.openStream()));
            String page = "";
            String inLine;

            while ((inLine = in.readLine()) != null) {
                page += inLine;
            }

            in.close();
            Bundle b = new Bundle();
            b.putString("result", page);
            m.setData(b);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        handler.sendMessage(m);
    }
}

4

Ho fatto questo per un servizio web per richiedere su URL, usando una libreria Gson:

Cliente:

public EstabelecimentoList getListaEstabelecimentoPorPromocao(){

        EstabelecimentoList estabelecimentoList  = new EstabelecimentoList();
        try{
            URL url = new URL("http://" +  Conexao.getSERVIDOR()+ "/cardapio.online/rest/recursos/busca_estabelecimento_promocao_android");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();

            if (con.getResponseCode() != 200) {
                    throw new RuntimeException("HTTP error code : "+ con.getResponseCode());
            }

            BufferedReader br = new BufferedReader(new InputStreamReader((con.getInputStream())));
            estabelecimentoList = new Gson().fromJson(br, EstabelecimentoList.class);
            con.disconnect();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return estabelecimentoList;
}

4

Guarda questa fantastica nuova libreria che è disponibile via gradle :)

build.gradle: compile 'com.apptakk.http_request:http-request:0.1.2'

Uso:

new HttpRequestTask(
    new HttpRequest("http://httpbin.org/post", HttpRequest.POST, "{ \"some\": \"data\" }"),
    new HttpRequest.Handler() {
      @Override
      public void response(HttpResponse response) {
        if (response.code == 200) {
          Log.d(this.getClass().toString(), "Request successful!");
        } else {
          Log.e(this.getClass().toString(), "Request unsuccessful: " + response);
        }
      }
    }).execute();

https://github.com/erf/http-request


1
Sembra ogni altra biblioteca ...
Nick Gallimore,

3

Usa Volley come suggerito sopra. Aggiungi il seguente in build.gradle (Modulo: app)

implementation 'com.android.volley:volley:1.1.1'

Aggiungi il seguente in AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

E aggiungi il seguente codice attività:

public void httpCall(String url) {

    RequestQueue queue = Volley.newRequestQueue(this);

    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // enjoy your response
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    // enjoy your error status
                }
    });

    queue.add(stringRequest);
}

Sostituisce il client http ed è molto semplice.


2

Questo è il nuovo codice per la richiesta HTTP Get / POST in Android. HTTPClientè deprecato e potrebbe non essere disponibile come nel mio caso.

Per prima cosa aggiungi le due dipendenze in build.gradle:

compile 'org.apache.httpcomponents:httpcore:4.4.1'
compile 'org.apache.httpcomponents:httpclient:4.5'

Quindi scrivere questo codice ASyncTasknel doBackgroundmetodo.

 URL url = new URL("http://localhost:8080/web/get?key=value");
 HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
 urlConnection.setRequestMethod("GET");
 int statusCode = urlConnection.getResponseCode();
 if (statusCode ==  200) {
      InputStream it = new BufferedInputStream(urlConnection.getInputStream());
      InputStreamReader read = new InputStreamReader(it);
      BufferedReader buff = new BufferedReader(read);
      StringBuilder dta = new StringBuilder();
      String chunks ;
      while((chunks = buff.readLine()) != null)
      {
         dta.append(chunks);
      }
 }
 else
 {
     //Handle else
 }

Il codice potrebbe diventare obsoleto e apache non è più supportato nell'API 28 della piattaforma Android. In tal caso, puoi abilitare la proprietà legacy di apache in Manifest o file Gradle a livello di modulo. Tuttavia, si consiglia di utilizzare la libreria di rete OKHttp, Volley o Retrofit.
Rahul Raina,

1

Per me, il modo più semplice è usare la libreria chiamata Retrofit2

Dobbiamo solo creare un'interfaccia che contenga il nostro metodo di richiesta, i parametri e possiamo anche creare un'intestazione personalizzata per ogni richiesta:

    public interface MyService {

      @GET("users/{user}/repos")
      Call<List<Repo>> listRepos(@Path("user") String user);

      @GET("user")
      Call<UserDetails> getUserDetails(@Header("Authorization") String   credentials);

      @POST("users/new")
      Call<User> createUser(@Body User user);

      @FormUrlEncoded
      @POST("user/edit")
      Call<User> updateUser(@Field("first_name") String first, 
                            @Field("last_name") String last);

      @Multipart
      @PUT("user/photo")
      Call<User> updateUser(@Part("photo") RequestBody photo, 
                            @Part("description") RequestBody description);

      @Headers({
        "Accept: application/vnd.github.v3.full+json",
        "User-Agent: Retrofit-Sample-App"
      })
      @GET("users/{username}")
      Call<User> getUser(@Path("username") String username);    

    }

E la cosa migliore è che possiamo farlo in modo asincrono facilmente usando il metodo accodamento


1

Poiché nessuna delle risposte ha descritto un modo per eseguire richieste con OkHttp , che è il client http molto popolare al giorno d'oggi per Android e Java in generale, fornirò un semplice esempio:

//get an instance of the client
OkHttpClient client = new OkHttpClient();

//add parameters
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://www.example.com").newBuilder();
urlBuilder.addQueryParameter("query", "stack-overflow");


String url = urlBuilder.build().toString();

//build the request
Request request = new Request.Builder().url(url).build();

//execute
Response response = client.newCall(request).execute();

Il chiaro vantaggio di questa libreria è che ci distrae da alcuni dettagli di basso livello, fornendo modi più amichevoli e sicuri per interagire con loro. La sintassi è anche semplificata e consente di scrivere un bel codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.