使用 android 发出 HTTP 请求

Posted

技术标签:

【中文标题】使用 android 发出 HTTP 请求【英文标题】:Make an HTTP request with android 【发布时间】:2011-03-31 04:10:51 【问题描述】:

我到处搜索,但找不到答案,有没有办法发出简单的 HTTP 请求?我想在我的一个网站上请求一个 php 页面/脚本,但我不想显示该网页。

如果可能的话,我什至想在后台(在广播接收器中)这样做

【问题讨论】:

相关:Download a resource, and show a progress dialog 这也是相关的:***.com/q/46177133/8583692 【参考方案1】:

更新

这是一个非常古老的答案。我绝对不会再推荐 Apache 的客户端了。而是使用:

Retrofit OkHttp Volley HttpUrlConnection

原答案

首先,请求访问网络的权限,将以下内容添加到您的清单中:

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

那么最简单的方法就是使用Android捆绑的Apache http客户端:

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

如果您希望它在单独的线程上运行,我建议您扩展 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..
    

然后您可以通过以下方式提出请求:

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

【讨论】:

这是一篇来自安卓开发者官方博客关于 AsyncTask 的文章:android-developers.blogspot.com/2010/07/… 对于姜饼或更高版本,实际上建议在 apache 库上使用 HttpURLConnection,请参阅android-developers.blogspot.com/2011/09/…。它对电池的负担更少,性能更好 responseString = out.toString() 需要在 out.close() 调用之前。实际上,您可能应该将 out.close() 放在 finally 块中。但总的来说,非常有帮助的答案 (+1),谢谢! 从 Honeycomb (SDK 11) 开始,异步方法是可行的方法。当您尝试从主线程运行 HTTP 请求时,会抛出 NetworkOnMainThreadException。 这个答案非常好。但我建议不要将 AsyncTasks 用于网络。他们可以很容易地造成内存泄漏(实际上提供的示例确实发生了泄漏),并且不提供网络请求的所有功能。考虑将 RoboSpice 用于此类后台任务:github.com/octo-online/robospice【参考方案2】:

按照上面的建议使用 Volley。将以下内容添加到 build.gradle (Module: app)

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

在 AndroidManifest.xml 中添加以下内容:

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

并向您添加以下活动代码:

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

它取代了http客户端,非常简单。

【讨论】:

但是这个请求是同步的,是吗?如何异步执行? 恕我直言,它是异步的。您的代码在queue.add(... 之后继续 它是异步的。我有相反的问题:如何发出阻塞的 HTTP(S) 请求?在queue.add() 之后没有组织一个繁忙的循环,即。【参考方案3】:

由于没有一个答案描述了使用OkHttp 执行请求的方法,这是现在对于 Android 和 Java 来说非常流行的 http 客户端,我将提供一个简单的示例:

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

这个库的明显优势在于它将我们从一些低级细节中抽象出来,提供了更友好和安全的方式来与它们交互。语法也得到了简化,允许编写漂亮的代码。

【讨论】:

【参考方案4】:

注意:与 Android 捆绑的 Apache HTTP 客户端现已弃用,取而代之的是 HttpURLConnection。详情请咨询 Android 开发者Blog。

&lt;uses-permission android:name="android.permission.INTERNET" /&gt; 添加到您的清单中。

然后你会像这样检索一个网页:

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

我还建议在单独的线程上运行它:

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


有关响应处理和 POST 请求的更多信息,请参阅documentation。

【讨论】:

@Semmix 怎么样?该问题要求“一个简单的 HTTP”请求,而我的代码正是这样做的。 我知道您的第一个代码块是从 Android 文档复制粘贴的,但人是样本/文档垃圾。 readStream 甚至没有定义。 @EugeneK 他们是,但这可能是回答这个问题的最简单的方法。在 Android 中正确执行 HTTP 请求需要解释 Retrofit 和 OkHttp。我认为这会让初学者感到困惑,而不仅仅是分发一个从技术上讲会发出简单 HTTP 请求的 sn-p,即使它的构造很差。【参考方案5】:

最简单的方法是使用名为Volley的Android lib

Volley 提供以下好处:

网络请求的自动调度。 多并发网络 连接。透明的磁盘和内存响应缓存 标准 HTTP 缓存一致性。支持请求优先级。 取消请求 API。您可以取消单个请求,也可以 设置要取消的请求块或范围。易于定制,适用于 例如,用于重试和退避。强大的排序使得它很容易 使用从 网络。调试和跟踪工具。

您可以像这样简单地发送 http/https 请求:

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

在这种情况下,您不必自己考虑“在后台运行”或“使用缓存”,因为所有这些都已由 Volley 完成。

【讨论】:

【参考方案6】:

对我来说,最简单的方法是使用名为 Retrofit2 的库

我们只需要创建一个包含我们的请求方法、参数的接口,我们还可以为每个请求制作自定义标头:

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

    

最好的是,我们可以使用 enqueue 方法轻松地异步完成

【讨论】:

【参考方案7】:

看看这个很棒的新库,它可以通过 gradle 获得:)

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

用法:

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

【讨论】:

【参考方案8】:

这是 android 中 HTTP Get/POST 请求的新代码。 HTTPClient 已被弃用,可能无法像我一样使用。

首先在build.gradle中添加两个依赖:

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

然后将这段代码写在ASyncTaskdoBackground方法中。

 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
 

【讨论】:

该代码可能会被弃用,并且 Android Platform API 28 不再支持 apache。在这种情况下,您可以在 Manifest 或模块级 Gradle 文件中启用 apache 旧属性。但是,建议使用 OKHttp、Volley 或 Retrofit 网络库。【参考方案9】:
private String getToServer(String service) throws IOException 
    HttpGet httpget = new HttpGet(service);
    ResponseHandler<String> responseHandler = new BasicResponseHandler();
    return new DefaultHttpClient().execute(httpget, responseHandler);


问候

【讨论】:

【参考方案10】:

我使用 Gson 库为 Web 服务请求 URL:

客户:

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;

【讨论】:

【参考方案11】:

有一个线程:

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

【讨论】:

【参考方案12】:

除非您有明确的理由选择 Apache HttpClient,否则您应该更喜欢 java.net.URLConnection。您可以在网络上找到大量有关如何使用它的示例。

自您发布原始帖子以来,我们还改进了 Android 文档:http://developer.android.com/reference/java/net/HttpURLConnection.html

我们已经在官方博客上讨论了取舍:http://android-developers.blogspot.com/2011/09/androids-http-clients.html

【讨论】:

为什么不推荐使用 Apache HttpClient? 我的一个同谋在官方博客上详细介绍了这一点:android-developers.blogspot.com/2011/09/… @ElliottHughes:我同意 100%。不可否认,Apache httpclient 提供了简单的方法和更抽象的协议视图,但 java 的原生 urlconnection 的用处丝毫不减。稍加动手,它就和 httpclient 一样简单易用,而且更便携 实际上,如果您观看视频 Google I/O 2010 - Android REST 客户端应用程序(youtube.com/watch?v=xHXn3Kg2IQE 57min21sec),您会发现 Apache HttpClient 是最推荐的。我引用 Virgil Dobjanschi(谷歌的一名软件工程师,在 Android Application Group 工作)“我只是建议你使用 HTTP Apache 客户端,因为它具有更强大的实现。HTTP 事务的 URL 连接类型并不是最有效的实施。它终止连接的方式有时会对网络产生不利影响。”

以上是关于使用 android 发出 HTTP 请求的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 上使用 cookie 发出 http 请求?

如何监控我的应用在 android 中发出的 HTTP(获取、发布等)请求

在 Android 中发出异步 HTTP 请求是不是有公认的最佳实践?

向 Google Play Android Developer API 发出 HTTP 发布请求

Nativescript如何在后台发出http请求

如何在 Android 中使用 Volley 库进行肥皂发布请求