使用Android HttpURLConnection进行Http Get请求

70

我是Java和安卓开发的新手,尝试创建一个简单的应用程序,通过http get请求联系web服务器并向数据库添加一些数据。

当我在电脑上使用Web浏览器进行调用时,它可以正常工作。然而,当我在安卓模拟器中运行应用程序时,没有数据被添加。

我已经在应用程序清单中添加了Internet权限,Logcat没有报告任何问题。

是否有人能帮助我找出问题所在?

以下是源代码:

package com.example.httptest;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class HttpTestActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView tv = new TextView(this);
        setContentView(tv);

        try {
            URL url = new URL("http://www.mysite.se/index.asp?data=99");
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.disconnect();
            tv.setText("Hello!");
        }
        catch (MalformedURLException ex) {
            Log.e("httptest",Log.getStackTraceString(ex)); 
        }
        catch (IOException ex) {
            Log.e("httptest",Log.getStackTraceString(ex));
        }   
    }        
}
7个回答

78

尝试从这里获取输入流,然后您可以通过以下方式获取文本数据:

    URL url;
    HttpURLConnection urlConnection = null;
    try {
        url = new URL("http://www.mysite.se/index.asp?data=99");

        urlConnection = (HttpURLConnection) url
                .openConnection();

        InputStream in = urlConnection.getInputStream();

        InputStreamReader isw = new InputStreamReader(in);

        int data = isw.read();
        while (data != -1) {
            char current = (char) data;
            data = isw.read();
            System.out.print(current);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();
        }    
    }

你可能也可以使用其他的输入流阅读器,如缓冲阅读器。

问题在于当你打开连接时,它并没有“拉取”任何数据。


10
你应该在 finally 块中关闭你的连接。 - Luigi Massa Gallerano
我故意使用了广泛的异常来避免方法变得过于冗长。用户应该在适当的情况下尽量使用更具体的异常。 - Davos555
我找不到断开连接时抛出的异常是什么? - Syed Ali
是的,对于 disconnect(),不需要 try catch,已经删除。 - Davos555

45

这里是一个完整的 AsyncTask 类。

public class GetMethodDemo extends AsyncTask<String , Void ,String> {
    String server_response;

    @Override
    protected String doInBackground(String... strings) {

        URL url;
        HttpURLConnection urlConnection = null;

        try {
            url = new URL(strings[0]);
            urlConnection = (HttpURLConnection) url.openConnection();

            int responseCode = urlConnection.getResponseCode();

            if(responseCode == HttpURLConnection.HTTP_OK){
                server_response = readStream(urlConnection.getInputStream());
                Log.v("CatalogClient", server_response);
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        Log.e("Response", "" + server_response);


    }
}

// Converting InputStream to String

private String readStream(InputStream in) {
        BufferedReader reader = null;
        StringBuffer response = new StringBuffer();
        try {
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return response.toString();
    }

要调用这个AsyncTask

new GetMethodDemo().execute("your web-service url");

19

我已经使用回调(delegate)创建了响应Activity类的功能。

public class WebService extends AsyncTask<String, Void, String> {

    private Context mContext;
    private OnTaskDoneListener onTaskDoneListener;
    private String urlStr = "";

    public WebService(Context context, String url, OnTaskDoneListener onTaskDoneListener) {
        this.mContext = context;
        this.urlStr = url;
        this.onTaskDoneListener = onTaskDoneListener;
    }

    @Override
    protected String doInBackground(String... params) {
        try {

            URL mUrl = new URL(urlStr);
            HttpURLConnection httpConnection = (HttpURLConnection) mUrl.openConnection();
            httpConnection.setRequestMethod("GET");
            httpConnection.setRequestProperty("Content-length", "0");
            httpConnection.setUseCaches(false);
            httpConnection.setAllowUserInteraction(false);
            httpConnection.setConnectTimeout(100000);
            httpConnection.setReadTimeout(100000);

            httpConnection.connect();

            int responseCode = httpConnection.getResponseCode();

            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line + "\n");
                }
                br.close();
                return sb.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        if (onTaskDoneListener != null && s != null) {
            onTaskDoneListener.onTaskDone(s);
        } else
            onTaskDoneListener.onError();
    }
}

何处

public interface OnTaskDoneListener {
    void onTaskDone(String responseData);

    void onError();
}

您可以根据自己的需求进行修改。它是用于获取的。


1
这非常有帮助。但我还有几个问题。变量mContext被赋值但从未被引用,它需要存在吗?另外,连接是否需要按照上面的注释进行断开? - John Ward
如果你不需要它,那就移除它。但大多数情况下我需要在AsyncTask中使用activity context。第二点是你在谈论setConnectTimeout吗?如果响应超过10秒钟延迟,你会面临一个“Android未响应”的消息。 - Zar E Ahmer
1
我是新手,所以正在尝试了解最佳实践。@Luigi 对 Davos555 评论说:“你应该在 finally 块中关闭连接”。我看到你有一个 br.close() 来关闭读取器,但是是否还应该有一个 httpConnection.disconnect(),或者这并不重要? - John Ward
1
是的,@John Ward,你说得对,连接也应该关闭。 - Zar E Ahmer

4

如果您只需要非常简单的调用,可以直接使用URL:

import java.net.URL;

    new URL("http://wheredatapp.com").openStream();

1
简单高效的解决方案:使用Volley。
 StringRequest stringRequest = new StringRequest(Request.Method.GET, finalUrl ,
           new Response.Listener<String>() {
                    @Override
                    public void onResponse(String){
                        try {
                            JSONObject jsonObject = new JSONObject(response);
                            HashMap<String, Object> responseHashMap = new HashMap<>(Utility.toMap(jsonObject)) ;
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.d("api", error.getMessage().toString());
            }
        });

        RequestQueue queue = Volley.newRequestQueue(context) ;
        queue.add(stringRequest) ;

0

使用Tasks和Kotlin在分离的线程上更现代化的方法

private val mExecutor: Executor = Executors.newSingleThreadExecutor()

private fun createHttpTask(u:String): Task<String> {
    return Tasks.call(mExecutor, Callable<String>{
        val url = URL(u)
        val conn: HttpURLConnection = url.openConnection() as HttpURLConnection
        conn.requestMethod = "GET"
        conn.connectTimeout = 3000
        conn.readTimeout = 3000
        val rc = conn.responseCode
        if ( rc != HttpURLConnection.HTTP_OK) {
            throw java.lang.Exception("Error: ${rc}")
        }
        val inp: InputStream = BufferedInputStream(conn.inputStream)
        val resp: String = inp.bufferedReader(UTF_8).use{ it.readText() }
        return@Callable resp
    })
}

现在你可以在很多地方像下面这样使用它:

            createHttpTask("https://google.com")
                    .addOnSuccessListener {
                        Log.d("HTTP", "Response: ${it}") // 'it' is a response string here
                    }
                    .addOnFailureListener {
                        Log.d("HTTP", "Error: ${it.message}") // 'it' is an Exception object here
                    }

-5

URL url = new URL("https://www.google.com");

//如果您正在使用

URLConnection conn =url.openConnection();

//请将其更改为

HttpURLConnection conn =(HttpURLConnection )url.openConnection();


他正在使用 HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); - Andre Hofmeister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接