Stellen Sie eine HTTP-Anfrage mit Android

352

Ich habe überall gesucht, aber ich konnte meine Antwort nicht finden. Gibt es eine Möglichkeit, eine einfache HTTP-Anfrage zu stellen? Ich möchte eine PHP-Seite / ein PHP-Skript auf einer meiner Websites anfordern, aber ich möchte die Webseite nicht anzeigen.

Wenn möglich möchte ich es sogar im Hintergrund machen (in einem BroadcastReceiver)

Mats Hofman
quelle

Antworten:

477

AKTUALISIEREN

Dies ist eine sehr alte Antwort. Ich werde Apaches Client definitiv nicht mehr empfehlen. Verwenden Sie stattdessen entweder:

Ursprüngliche Antwort

Fordern Sie zunächst eine Berechtigung zum Zugriff auf das Netzwerk an und fügen Sie Ihrem Manifest Folgendes hinzu:

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

Der einfachste Weg ist dann, den mit Android gebündelten Apache http-Client zu verwenden:

    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());
    }

Wenn Sie möchten, dass es auf einem separaten Thread ausgeführt wird, würde ich empfehlen, AsyncTask zu erweitern:

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..
    }
}

Sie können dann eine Anfrage stellen, indem Sie:

   new RequestTask().execute("http://stackoverflow.com");
Konstantin Burov
quelle
11
Hier ist ein Artikel aus dem offiziellen Android-Entwickler-Blog auf AsyncTask: android-developers.blogspot.com/2010/07/…
Austyn Mahoney
77
Für Lebkuchen oder höher wird empfohlen, HttpURLConnection über die Apache-Bibliothek zu verwenden, siehe android-developers.blogspot.com/2011/09/… . Es ist weniger anstrengend für die Batterie und hat eine bessere Leistung
Marty
8
responseString = out.toString () muss vor dem Aufruf von out.close () stehen. Eigentlich sollten Sie wahrscheinlich die Datei out.close () in einem finally-Block haben. Aber insgesamt sehr hilfreiche Antwort (+1), danke!
DCP
9
Ab Honeycomb (SDK 11) ist der asynchrone Ansatz der richtige Weg. Eine NetworkOnMainThreadException wird ausgelöst, wenn Sie versuchen, eine HTTP-Anforderung vom Hauptthread auszuführen.
Msrxthr
2
Diese Antwort ist sehr gut. Ich würde jedoch raten, AsyncTasks nicht für das Netzwerk zu verwenden. Sie können sehr leicht Speicherlecks verursachen (und das bereitgestellte Beispiel leckt tatsächlich) und bieten nicht alle Funktionen, die man für Netzwerkanforderungen erwarten kann. Erwägen Sie die Verwendung von RoboSpice für diese Art von Hintergrundaufgaben: github.com/octo-online/robospice
Snicolas
67

Sofern Sie keinen expliziten Grund haben, sich für den Apache HttpClient zu entscheiden, sollten Sie java.net.URLConnection bevorzugen. Im Web finden Sie zahlreiche Beispiele für die Verwendung.

Wir haben auch die Android-Dokumentation seit Ihrem ursprünglichen Beitrag verbessert: http://developer.android.com/reference/java/net/HttpURLConnection.html

und wir haben im offiziellen Blog über die Kompromisse gesprochen: http://android-developers.blogspot.com/2011/09/androids-http-clients.html

Elliott Hughes
quelle
13
Warum wird die Verwendung von Apache HttpClient nicht empfohlen?
Ted
4
Ein Mitverschwörer von mir ging im offiziellen Blog ausführlich darauf ein: android-developers.blogspot.com/2011/09/…
Elliott Hughes
@ ElliottHughes: Ich stimme 100% zu. Es ist nicht zu leugnen, dass Apache httpclient einfache Methoden und eine abstraktere Ansicht des Protokolls bietet, aber die native URL-Verbindung von Java ist keineswegs weniger nützlich. Mit ein bisschen Hands-on ist es so einfach zu bedienen wie httpclient und viel portabler
Nitin Bansal
1
Wenn Sie sich das Video Google I / O 2010 - Android REST-Clientanwendungen ( youtube.com/watch?v=xHXn3Kg2IQE 57min21sec) ansehen, werden Sie feststellen, dass Apache HttpClient die am meisten empfohlene ist. Ich zitiere Virgil Dobjanschi (einen Softwareentwickler bei Google, der mit Android Application Group arbeitet). "Ich würde einfach empfehlen, dass Sie den HTTP-Apache-Client verwenden, da er eine robustere Implementierung aufweist. Der URL-Verbindungstyp der HTTP-Transaktion ist nicht der effizienteste Implementierung. Und die Art und Weise, wie Verbindungen manchmal beendet werden, kann sich nachteilig auf das Netzwerk auswirken. "
Alan
46

Hinweis: Der mit Android mitgelieferte Apache HTTP-Client ist jetzt zugunsten von HttpURLConnection veraltet . Weitere Informationen finden Sie im Android Developers Blog .

Fügen Sie <uses-permission android:name="android.permission.INTERNET" />Ihrem Manifest hinzu.

Sie würden dann eine Webseite wie folgt abrufen:

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();
}

Ich schlage auch vor, es in einem separaten Thread auszuführen:

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..
}
}

Weitere Informationen zur Antwortbehandlung und zu POST-Anforderungen finden Sie in der Dokumentation .

kevinc
quelle
1
@Semmix Wie so? Die Frage nach "einer einfachen HTTP" -Anforderung, und mein Code macht genau das.
Kevin
1
Ich verstehe, dass Ihr erster Codeblock aus Android-Dokumenten kopiert wird, aber Mann ist dieser Beispiel- / Dokumentmüll. readStreamist nicht einmal definiert.
Eugene K
@EugeneK Sie sind, aber dies ist wahrscheinlich der einfachste Weg, um diese Frage zu beantworten. Um eine HTTP-Anforderung in Android ordnungsgemäß auszuführen, müssen Retrofit und OkHttp erläutert werden. Ich denke, das würde Anfänger mehr verwirren als nur ein Snippet zu verteilen, das technisch eine einfache HTTP-Anfrage stellt, selbst wenn es schlecht aufgebaut ist.
Kevin
12

Der einfachste Weg ist die Verwendung der Android-Bibliothek namens Volley

Volley bietet folgende Vorteile:

Automatische Planung von Netzwerkanforderungen. Mehrere gleichzeitige Netzwerkverbindungen . Transparentes Festplatten- und Speicherantwort-Caching mit Standard-HTTP-Cache-Kohärenz. Unterstützung für die Priorisierung von Anforderungen. Stornierungsanforderungs-API. Sie können eine einzelne Anforderung stornieren oder Blöcke oder Bereiche von Anforderungen festlegen, die abgebrochen werden sollen. Einfache Anpassung, zum Beispiel für Wiederholungsversuche und Backoffs. Starke Reihenfolge, die es einfach macht, Ihre Benutzeroberfläche korrekt mit Daten zu füllen, die asynchron aus dem Netzwerk abgerufen werden. Debugging- und Tracing-Tools.

Sie können eine http / https-Anfrage so einfach senden:

        // 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 diesem Fall müssen Sie nicht in Betracht ziehen, selbst im Hintergrund zu laufen oder den Cache zu verwenden, da all dies bereits von Volley durchgeführt wurde.

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

}

Grüße

Gabriel Gómez
quelle
4

Mit einem Thread:

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);
    }
}
Fredley
quelle
4

Ich habe dies für einen Webservice gemacht, um eine URL mit einer Gson-Bibliothek anzufordern:

Klient:

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;
}
Deividson Calixto
quelle
4

Schau dir diese tolle neue Bibliothek an, die über gradle erhältlich ist :)

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

Verwendungszweck:

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

Electronix384128
quelle
1
Scheint wie jede andere Bibliothek ...
Nick Gallimore
3

Verwenden Sie Volley wie oben vorgeschlagen. Fügen Sie Folgendes zu build.gradle hinzu (Modul: App)

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

Fügen Sie Folgendes in AndroidManifest.xml hinzu:

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

Fügen Sie Ihrem Aktivitätscode Folgendes hinzu:

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);
}

Es ersetzt den http-Client und ist sehr einfach.

Jarda Pavlíček
quelle
2

Dies ist der neue Code für die HTTP-Get / POST-Anforderung in Android. HTTPClientist benachteiligt und möglicherweise nicht so verfügbar wie in meinem Fall.

Fügen Sie zunächst die beiden Abhängigkeiten in build.gradle hinzu:

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

Dann schreiben Sie diesen Code in ASyncTaskin doBackgroundMethode.

 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
 }
Rahul Raina
quelle
Der Code wird möglicherweise veraltet und Apache wird in der Android Platform API 28 nicht mehr unterstützt. In diesem Fall können Sie die Apache-Legacy-Eigenschaft in der Gradle-Datei auf Manifest- oder Modulebene aktivieren. Es wird jedoch empfohlen, die Netzwerkbibliothek OKHttp, Volley oder Retrofit zu verwenden.
Rahul Raina
1

Für mich ist der einfachste Weg die Verwendung der Bibliothek Retrofit2

Wir müssen nur eine Schnittstelle erstellen, die unsere Anforderungsmethode und Parameter enthält, und wir können für jede Anforderung einen benutzerdefinierten Header erstellen:

    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);    

    }

Und das Beste ist, wir können es asynchron einfach mit der Enqueue-Methode machen

faruk
quelle
1

Da in keiner der Antworten eine Möglichkeit zum Ausführen von Anforderungen mit OkHttp beschrieben wurde, einem heutzutage sehr beliebten http-Client für Android und Java im Allgemeinen, werde ich ein einfaches Beispiel geben:

//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();

Der klare Vorteil dieser Bibliothek besteht darin, dass sie uns von einigen Details auf niedriger Ebene abstrahiert und freundlichere und sicherere Möglichkeiten für die Interaktion mit ihnen bietet. Die Syntax ist ebenfalls vereinfacht und ermöglicht das Schreiben von schönem Code.

NiVeR
quelle