Faça uma solicitação HTTP com android

352

Eu procurei em todos os lugares, mas não consegui encontrar minha resposta. Existe uma maneira de fazer uma solicitação HTTP simples? Quero solicitar uma página / script PHP em um dos meus sites, mas não quero mostrar a página da web.

Se possível, eu quero fazer isso em segundo plano (em um BroadcastReceiver)

Mats Hofman
fonte

Respostas:

477

ATUALIZAR

Esta é uma resposta muito antiga. Definitivamente, não recomendarei mais o cliente do Apache. Em vez disso, use:

Resposta original

Primeiro, solicite uma permissão para acessar a rede e adicione o seguinte ao seu manifesto:

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

A maneira mais fácil é usar o cliente http Apache incluído no 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 você deseja que ele seja executado em um thread separado, recomendo estender o 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..
    }
}

Você pode fazer uma solicitação:

   new RequestTask().execute("http://stackoverflow.com");
Konstantin Burov
fonte
11
Aqui está um artigo do blog do desenvolvedor android oficial sobre AsyncTask: android-developers.blogspot.com/2010/07/...
Austyn Mahoney
77
para pão de mel ou superior, é realmente recomendável usar o HttpURLConnection na biblioteca apache, consulte android-developers.blogspot.com/2011/09/… . Sua menos desgastante para a bateria e tem melhor desempenho
Marty
8
responseString = out.toString () precisa estar antes da chamada out.close (). Na verdade, você provavelmente deve ter o out.close () em um bloco finalmente. Mas, em geral, resposta muito útil (+1), obrigado!
dcp
9
A partir do Honeycomb (SDK 11), a abordagem assíncrona é o caminho a seguir. Uma NetworkOnMainThreadException é lançada quando você tenta executar uma solicitação HTTP a partir do thread principal.
precisa saber é
2
Esta resposta é excelente. Mas eu aconselho a não usar AsyncTasks for Networking. Eles podem criar vazamentos de memória com muita facilidade (e, na verdade, o exemplo fornecido vaza) e não fornecem todos os recursos que se pode esperar para solicitações de rede. Considere o uso de RoboSpice para este tipo de tarefas de fundo: github.com/octo-online/robospice
Snicolas
67

a menos que você tenha um motivo explícito para escolher o Apache HttpClient, você deve preferir java.net.URLConnection. você pode encontrar muitos exemplos de como usá-lo na web.

também aprimoramos a documentação do Android desde sua postagem original: http://developer.android.com/reference/java/net/HttpURLConnection.html

e conversamos sobre as compensações no blog oficial: http://android-developers.blogspot.com/2011/09/androids-http-clients.html

Elliott Hughes
fonte
13
Por que o Apache HttpClient não é recomendado?
Ted
4
Um co-conspirador meu entrou nisso em detalhes no blog oficial: android-developers.blogspot.com/2011/09/…
Elliott Hughes
@ ElliottHughes: Eu concordo 100%. Não há como negar que o httpclient do Apache oferece métodos fáceis e uma visão mais abstrata do protocolo, mas a conexão de URL nativa do java não é de forma alguma menos útil. Com um pouco de hands-on, a sua tão fácil de usar httpclient como, e é a maneira mais portátil
Nitin Bansal
11
Na verdade, se você der uma olhada no vídeo Google I / O 2010 - aplicativos clientes REST Android ( youtube.com/watch?v=xHXn3Kg2IQE 57min21sec), verá que o Apache HttpClient é o mais recomendado. Cito Virgil Dobjanschi (um engenheiro de software no google que trabalha no Android Application Group) "Eu simplesmente aconselho que você use o cliente HTTP Apache, porque ele tem uma implementação mais robusta. O tipo de conexão URL da transação HTTP não é a mais eficiente implementação. E a maneira como termina as conexões às vezes pode ter um efeito adverso na rede. "
Alan
46

Nota: O Apache HTTP Client incluído no Android agora está obsoleto em favor do HttpURLConnection . Consulte o Blog dos desenvolvedores do Android para obter mais detalhes.

Adicionar <uses-permission android:name="android.permission.INTERNET" /> ao seu manifesto.

Você recuperaria uma página da Web da seguinte maneira:

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

Eu também sugiro executá-lo em um thread separado:

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

Consulte a documentação para obter mais informações sobre manipulação de resposta e solicitações POST.

kevinc
fonte
11
@Smmix Como assim? A pergunta era "um simples HTTP" e meu código faz exatamente isso.
Kevinc
11
Entendo que seu primeiro bloco de código é uma cópia colada de documentos do Android, mas o homem é esse exemplo / lixo de documento. readStreamnem está definido.
Eugene K
@ EugeneK Eles são, mas esta é provavelmente a maneira mais simples de responder a essa pergunta. Fazer uma solicitação HTTP corretamente no Android envolveria a explicação de Retrofit e OkHttp. Eu acho que isso confundiria os iniciantes mais do que apenas distribuir um trecho que tecnicamente fará uma solicitação HTTP simples, mesmo que seja mal construída.
Kevinc #
12

A maneira mais simples é usar a biblioteca Android chamada Volley

O Volley oferece os seguintes benefícios:

Agendamento automático de solicitações de rede. Várias conexões de rede simultâneas . Cache transparente de resposta de disco e memória com coerência de cache HTTP padrão. Suporte para priorização de solicitação. API de solicitação de cancelamento. Você pode cancelar uma única solicitação ou definir blocos ou escopos de solicitações para cancelar. Facilidade de personalização, por exemplo, para repetição e retirada. Ordenação forte que facilita o preenchimento correto da interface do usuário com dados obtidos de forma assíncrona na rede. Ferramentas de depuração e rastreamento.

Você pode enviar uma solicitação http / https tão simples quanto isto:

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

Nesse caso, você não precisa considerar "executar em segundo plano" ou "usar cache", pois tudo isso já foi feito pelo Volley.

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

}

Saudações

Gabriel Gómez
fonte
4

Com um fio:

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
fonte
4

Fiz isso para um serviço da Web solicitar a URL, usando uma biblioteca 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;
}
Deividson Calixto
fonte
4

Olhe para esta nova biblioteca incrível que está disponível 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

electronix384128
fonte
11
Parece que qualquer outra biblioteca ...
Nick Gallimore 12/02
3

Use Volley como sugerido acima. Adicione o seguinte ao build.gradle (Módulo: app)

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

Adicione o seguinte ao AndroidManifest.xml:

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

E adicione o seguinte ao seu código de atividade:

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

Ele substitui o cliente http e é muito simples.

Jarda Pavlíček
fonte
2

Este é o novo código para solicitação HTTP Get / POST no Android. HTTPClientestá privado e pode não estar disponível como estava no meu caso.

Primeiro, adicione as duas dependências no build.gradle:

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

Em seguida, escreva esse código ASyncTaskno doBackgroundmétodo

 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
fonte
O código pode ficar obsoleto e o apache não é mais suportado na API da plataforma Android 28. Nesse caso, você pode ativar a propriedade herdada do apache no arquivo Manifest ou no nível do módulo Gradle. No entanto, é recomendável usar a biblioteca de rede OKHttp, Volley ou Retrofit.
Rahul Raina
1

Para mim, a maneira mais fácil é usar a biblioteca chamada Retrofit2

Nós apenas precisamos criar uma interface que contenha nosso método de solicitação, parâmetros e também podemos criar um cabeçalho personalizado para cada solicitação:

    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 o melhor é que podemos fazê-lo de forma assíncrona facilmente usando o método de enfileiramento

faruk
fonte
1

Como nenhuma das respostas descreveu uma maneira de executar solicitações com o OkHttp , que é um cliente http muito popular hoje em dia para Android e Java em geral, vou fornecer um exemplo simples:

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

A clara vantagem desta biblioteca é que ela nos abstrai de alguns detalhes de baixo nível, fornecendo maneiras mais amigáveis ​​e seguras de interagir com elas. A sintaxe também é simplificada e permite escrever um bom código.

NiVeR
fonte