Android 获取纬度和经度会给我NetworkOnMainThreadException

Android 获取纬度和经度会给我NetworkOnMainThreadException,android,json,networkonmainthread,Android,Json,Networkonmainthread,我试图通过输入一个字符串并将其发送到GoogleGeocode,然后用JSON返回来获取经度和纬度。但是每当我运行这段代码时,我都会得到一个NetworkOnMainThreadException。为什么呢?我如何解决这个问题 public class SearchAddressActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { supe

我试图通过输入一个字符串并将其发送到GoogleGeocode,然后用JSON返回来获取经度和纬度。但是每当我运行这段代码时,我都会得到一个
NetworkOnMainThreadException
。为什么呢?我如何解决这个问题

public class SearchAddressActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search_on_address);

        getLocationInfo("New Cross rd SE146AS London");
    }


    public JSONObject getLocationInfo(String address) {

        address = address.replaceAll(" ", "%20");
        Double lon = new Double(0);
        Double lat = new Double(0);
        HttpGet httpGet = new HttpGet("http://maps.google.com/maps/api/geocode/json?address="+ address + "&sensor=false");
        HttpClient client = new DefaultHttpClient();
        HttpResponse response;
        StringBuilder stringBuilder = new StringBuilder();

        try {
            response = client.execute(httpGet);
            HttpEntity entity = response.getEntity();
            InputStream stream = entity.getContent();
            int b;
            while ((b = stream.read()) != -1) {
                stringBuilder.append((char) b);
            }
        } catch (ClientProtocolException e) {
        } catch (IOException e) {
        }

        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject = new JSONObject(stringBuilder.toString());
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            lon = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
                    .getJSONObject("geometry").getJSONObject("location")
                    .getDouble("lng");

            lat = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
                    .getJSONObject("geometry").getJSONObject("location")
                    .getDouble("lat");

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Log.e("LON", String.valueOf(lon));
        Log.e("LAT", String.valueOf(lat));
        return jsonObject;
    }   
}
Logcat

06-14 00:38:21.675: E/AndroidRuntime(18999): FATAL EXCEPTION: main
06-14 00:38:21.675: E/AndroidRuntime(18999): java.lang.RuntimeException: Unable to start activity ComponentInfo{eu.mysite.www/eu.mysite.www.SearchAddressActivity}: android.os.NetworkOnMainThreadException
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.ActivityThread.access$600(ActivityThread.java:140)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.os.Handler.dispatchMessage(Handler.java:99)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.os.Looper.loop(Looper.java:137)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.ActivityThread.main(ActivityThread.java:4898)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at java.lang.reflect.Method.invokeNative(Native Method)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at java.lang.reflect.Method.invoke(Method.java:511)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at dalvik.system.NativeStart.main(Native Method)
06-14 00:38:21.675: E/AndroidRuntime(18999): Caused by: android.os.NetworkOnMainThreadException
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at java.net.InetAddress.getAllByName(InetAddress.java:214)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:670)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:509)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at eu.mysite.www.SearchAddressActivity.getLocationInfo(SearchAddressActivity.java:47)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at eu.mysite.www.SearchAddressActivity.onCreate(SearchAddressActivity.java:32)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.Activity.performCreate(Activity.java:5206)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1083)
06-14 00:38:21.675: E/AndroidRuntime(18999):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
06-14 00:38:21.675: E/AndroidRuntime(18999):    ... 11 more

错误日志中的重要行是:

android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)
它说“有什么东西”阻止了这个请求——特别是操作系统(感谢Brian Roach说得很清楚)。您必须显式地将网络请求放在与UI线程不同的线程中,否则您的UI将挂起,直到网络响应为止

有关如何正确提出请求的示例,请参见Victor Lap的回答


我还建议您对查询进行正确的URL编码-“空格”不是唯一会引起麻烦的字符…

错误说明了一切,您不应该在主线程上执行网络操作。
阅读有关进程和线程以及如何使用它们的页面
和页面介绍如何在不同线程上正确使用网络

示例:(来自)

//使用AsyncTask创建远离主UI线程的任务。这项任务需要一段时间
//URL字符串,并使用它创建HttpUrlConnection。一旦连接
//已建立,AsyncTask将下载网页的内容,如下所示
//输入流。最后,InputStream被转换成一个字符串,它是
//通过AsyncTask的onPostExecute方法在UI中显示。
私有类下载WebPagetTask扩展异步任务{
@凌驾
受保护的字符串doInBackground(字符串…URL){
//params来自execute()调用:params[0]是url。
试一试{
返回下载URL(URL[0]);
}捕获(IOE异常){
return“无法检索网页。URL可能无效。”;
}
}
//onPostExecute显示异步任务的结果。
@凌驾
受保护的void onPostExecute(字符串结果){
setText(结果);
}
}

是的,那个“东西”就是安卓。例外情况正好说明了问题所在(摆弄URL也无济于事)。他们做到了这一点,所以新手不能用(阻止)网络调用来捆绑用户界面线程,以免伤到自己的脚。@BrianRoach-谢谢你的评论。现在改进我的答案…(顺便说一句,我不是落选者,否则我会取消它)@BrianRoach-没关系:-)。你的观点是正确的,最初的答案可能被认为是不够的。。。
 // Uses AsyncTask to create a task away from the main UI thread. This task takes a 
 // URL string and uses it to create an HttpUrlConnection. Once the connection
 // has been established, the AsyncTask downloads the contents of the webpage as
 // an InputStream. Finally, the InputStream is converted into a string, which is
 // displayed in the UI by the AsyncTask's onPostExecute method.
 private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {

        // params comes from the execute() call: params[0] is the url.
        try {
            return downloadUrl(urls[0]);
        } catch (IOException e) {
            return "Unable to retrieve web page. URL may be invalid.";
        }
    }
    // onPostExecute displays the results of the AsyncTask.
    @Override
    protected void onPostExecute(String result) {
        textView.setText(result);
   }
}