AutoCompleteTextView 没有从 Google 个地方 API 获得建议

AutoCompleteTextView is not getting the suggestions from Google Places API

这是我的代码,用于从 Google 个地点 API 获取地点建议。但它显示了一些错误,如 "Cannot connect to Google Places API"。我已经给出了我在这段代码底部得到的正确错误。

我只需要一个 AutoCompleteTextView 来填充 GeoLocations。例如,如果用户输入 "Deh",从 Deh 开始的建议应该立即出现,例如 "Dehradun, India"

 public class MainActivity extends ActionBarActivity {

        Button selectRoute;
        private static final String LOG_TAG = "Google Places Autocomplete";
        private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
        private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
        private static final String OUT_JSON = "/json";

        private static final String API_KEY = "My API Key";


        AutoCompleteTextView home;
        RadioButton yes, no;

        Spinner location, facility;



        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);


            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog()
                    .penaltyDeath().build());
            selectRoute = (Button) findViewById(R.id.button);
            home = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);


            home.setAdapter(new GooglePlacesAutocompleteAdapter(this, R.layout.list));
            home.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    String str = (String) adapterView.getItemAtPosition(i);
                    Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
                }
            });
            home.setThreshold(1);


        }


            @Override
            public boolean onCreateOptionsMenu(Menu menu) {

                return true;
            }

            @Override
            public boolean onOptionsItemSelected(MenuItem item) {

                int id = item.getItemId();

                return super.onOptionsItemSelected(item);
            }

            //____________________________________________________________________________________

        public static ArrayList autocomplete(String input) {
            ArrayList resultList = null;

            HttpURLConnection conn = null;
            StringBuilder jsonResults = new StringBuilder();
            try {
                StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
                sb.append("?key=" + API_KEY);

                sb.append("&input=" + URLEncoder.encode(input, "utf8"));

                URL url = new URL(sb.toString());
                conn = (HttpURLConnection) url.openConnection();
                InputStreamReader in = new InputStreamReader(conn.getInputStream());

                int read;
                char[] buff = new char[1024];
                while ((read = in.read(buff)) != -1) {
                    jsonResults.append(buff, 0, read);
                }
            } catch (MalformedURLException e) {
                Log.e(LOG_TAG, "Error processing Places API URL", e);
                return resultList;
            } catch (IOException e) {
                Log.e(LOG_TAG, "Error connecting to Places API", e);
                return resultList;
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }

            try {

                JSONObject jsonObj = new JSONObject(jsonResults.toString());
                JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");


                resultList = new ArrayList(predsJsonArray.length());
                for (int i = 0; i < predsJsonArray.length(); i++) {
                    System.out.println(predsJsonArray.getJSONObject(i).getString("description"));
                    System.out.println("============================================================");
                    resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
                }
            } catch (JSONException e) {
                Log.e(LOG_TAG, "Cannot process JSON results", e);
            }

            return resultList;
        }

        class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable {
            private ArrayList resultList;

            public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId) {
                super(context, textViewResourceId);
            }

            @Override
            public int getCount() {
                return resultList.size();
            }

            /*@Override
            public String getItem(int index) {
                return resultList.get(index);
            }*/

            @Override
            public Filter getFilter() {
                Filter filter = new Filter() {
                    @Override
                    protected FilterResults performFiltering(CharSequence constraint) {
                        FilterResults filterResults = new FilterResults();
                        if (constraint != null) {

                            resultList = autocomplete(constraint.toString());


                            filterResults.values = resultList;
                            filterResults.count = resultList.size();
                        }
                        return filterResults;
                    }

                    @Override
                    protected void publishResults(CharSequence constraint, FilterResults results) {
                        if (results != null && results.count > 0) {
                            notifyDataSetChanged();
                        } else {
                            notifyDataSetInvalidated();
                        }
                    }
                };
                return filter;
            }
        }

这是我遇到的错误。

1691-1709/? E/Google Places Autocomplete﹕ Error connecting to Places API
    java.net.ConnectException: failed to connect to maps.googleapis.com/74.125.130.95 (port 443): connect failed: ETIMEDOUT (Connection timed out)
            at libcore.io.IoBridge.connect(IoBridge.java:114)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
            at java.net.Socket.connect(Socket.java:843)
            at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)
            at com.android.okhttp.Connection.connect(Connection.java:101)
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
            at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:179)
            at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:246)
            at com.mycompany.com.shareadrive.MainActivity.autocomplete(MainActivity.java:143)
            at com.mycompany.com.shareadrive.MainActivity$GooglePlacesAutocompleteAdapter.performFiltering(MainActivity.java:207)
            at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.os.HandlerThread.run(HandlerThread.java:61)
     Caused by: libcore.io.ErrnoException: connect failed: ETIMEDOUT (Connection timed out)
            at libcore.io.Posix.connect(Native Method)
            at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85)
            at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
            at libcore.io.IoBridge.connect(IoBridge.java:112)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
            at java.net.Socket.connect(Socket.java:843)
            at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)
            at com.android.okhttp.Connection.connect(Connection.java:101)
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
            at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:179)
            at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:246)
            at com.mycompany.com.shareadrive.MainActivity.autocomplete(MainActivity.java:143)
            at com.mycompany.com.shareadrive.MainActivity$GooglePlacesAutocompleteAdapter.performFiltering(MainActivity.java:207)
            at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.os.HandlerThread.run(HandlerThread.java:61)

这是我收到的更新后的日志错误。

E/Google Places Autocomplete﹕ Error connecting to Places API
    java.net.SocketTimeoutException: failed to connect to maps.googleapis.com/74.125.200.95 (port 443) after 15000ms
            at libcore.io.IoBridge.connectErrno(IoBridge.java:159)
            at libcore.io.IoBridge.connect(IoBridge.java:112)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
            at java.net.Socket.connect(Socket.java:843)
            at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)
            at com.android.okhttp.Connection.connect(Connection.java:101)
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
            at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:179)
            at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:246)
            at com.mycompany.com.shareadrive.MainActivity.autocomplete(MainActivity.java:136)
            at com.mycompany.com.shareadrive.MainActivity$GooglePlacesAutocompleteAdapter.performFiltering(MainActivity.java:199)
            at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.os.HandlerThread.run(HandlerThread.java:61)
07-28 03:32:05.900    1785-1829/? W/Filter﹕ An exception occured during performFiltering()!
    java.lang.NullPointerException
            at com.mycompany.com.shareadrive.MainActivity$GooglePlacesAutocompleteAdapter.performFiltering(MainActivity.java:203)
            at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.os.HandlerThread.run(HandlerThread.java:61)

我刚刚测试了构建 url 的代码,它看起来不错,所以这不是问题所在。

您可能因连接速度慢而超时,请尝试在 HttpURLConnection 上设置超时:

conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(15000); //added

另外请注意,如果您还没有这样做,您将需要在后台线程中执行您的网络操作,使用 AsyncTask 将适合像这样的短操作。

编辑:

我只是 运行 你原始代码的精简版,它对我来说工作得很好。

我使用浏览器密钥作为 API 键,运行 AsyncTask 中的 autocomplete() 方法,并使用 "San Francisco" 硬编码进行测试。

这是我使用的完整 Activity class 代码:

public class MainActivity extends ActionBarActivity {

    Button testButton;
    TextView results;
    private static final String LOG_TAG = "PlacesAPI";
    private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
    private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
    private static final String OUT_JSON = "/json";

    private static final String API_KEY = "my-api-key-here";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        results = (TextView) findViewById(R.id.result);

        testButton = (Button) findViewById(R.id.button);

        testButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                new GetAutocompleteAsync().execute();
            }
        });
    }

    class GetAutocompleteAsync extends AsyncTask<String, String, ArrayList<String>>{

        @Override
        protected ArrayList<String> doInBackground(String... params) {

            ArrayList<String> results = autocomplete("San Francisco");
            return results;
        }

        @Override
        protected void onPostExecute(ArrayList<String> resultArrayList) {
            if (resultArrayList != null) {
                results.setText(resultArrayList.toString());
            }
        }

    }


    public static ArrayList autocomplete(String input) {
        ArrayList resultList = null;

        HttpURLConnection conn = null;
        StringBuilder jsonResults = new StringBuilder();
        try {
            StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
            sb.append("?key=" + API_KEY);

            sb.append("&input=" + URLEncoder.encode(input, "utf8"));

            URL url = new URL(sb.toString());
            conn = (HttpURLConnection) url.openConnection();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());

            int read;
            char[] buff = new char[1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error processing API URL", e);
            return resultList;
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error connecting to Places API", e);
            return resultList;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        try {

            JSONObject jsonObj = new JSONObject(jsonResults.toString());
            JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");


            resultList = new ArrayList(predsJsonArray.length());
            for (int i = 0; i < predsJsonArray.length(); i++) {
                System.out.println(predsJsonArray.getJSONObject(i).getString("description"));
                System.out.println("============================================================");
                resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
            }
        } catch (JSONException e) {
            Log.e(LOG_TAG, "Cannot process JSON results", e);
        }

        return resultList;
    }
}

这是生成的日志:

I/System.out﹕ San Francisco, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco, San Antonio, TX, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco International Airport, San Francisco, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco County, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco De La Espada, Espada Road, San Antonio, TX, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco, San Antonio, TX, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco International Airport, San Francisco, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco County, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco De La Espada, Espada Road, San Antonio, TX, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco, San Antonio, TX, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco International Airport, San Francisco, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco County, CA, United States
I/System.out﹕ ============================================================
I/System.out﹕ San Francisco De La Espada, Espada Road, San Antonio, TX, United States
I/System.out﹕ ============================================================

仅供参考:避免 ActionBarActivity。它已被弃用。试试这个 Android – AutoCompleteTextView with Google Places Autocomplete API