4

So part of my application builds a navigation directions string and then attempts to parse the JSON and draw the polyline routes on my map. I first build my string using Location variables or Locale constants. I end up with something like

https://maps.googleapis.com/maps/api/directions/json?origin=Full Frame Documentary Film 
Festival, Durham, 27701&destination=601 W Peace St, Raleigh,27605&sensor=false&key={API_KEY}
  • there is no new line (I added it for readability) and the {API_KEY} is my actual api key.

The issue that I am running into is that when I pass that URL String to this downloadUrl(String urlString) method

private String downloadUrl(String urlString) throws IOException {
    Log.d(TAG, "Downloaded string = " + urlString);
    String data = "";
    InputStream stream = null;
    HttpURLConnection urlConnection = null;
    try {

        // Display our JSON in our browser (to show us how we need to implement our parser)
        Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(urlString)); 
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

        URL url = new URL(urlString);

        // Create a http connection to communicate with url
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.connect();

        // read in our data
        stream = urlConnection.getInputStream(); 
        BufferedReader br = new BufferedReader(new InputStreamReader(stream)); 
        StringBuffer sb = new StringBuffer();   

        // read in our data in, and append it as a single data string
        String line = "";
        while ((line = br.readLine()) != null) {
            Log.d(TAG,"url download stream: " + line);
            sb.append(line);
        }
        data = sb.toString();
        br.close();
    } 
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        Log.d(TAG, "Downloaded data = " + data);
        stream.close();
        urlConnection.disconnect();
    }

    return data;
}    

the JSON displays in my browser correctly, I see everything as Google describes it in the documentation. But then in the following lines when I try to open a connection to the URL and pull the JSON into a string for parsing, I get the System.err notification

05-02 09:56:01.540: W/System.err(32232): java.io.FileNotFoundException: 
https://maps.googleapis.com/maps/api/directions/json?origin=Full Frame Documentary 
Film Festival, Durham, 27701&destination=601 W Peace St, Raleigh, 27605&sensor=false&key={API_KEY}

I guess my confusion comes in the fact that the browser displays the parsed address perfectly, but then the connection to (what I believe is) the same server returns a FNFE. Am I wrong in assuming that this is the case? If so might my key actually be wrong? The confusing thing is that this code works in another application.

zgc7009
  • 3,371
  • 5
  • 22
  • 34
  • Another thing: not sure, but it seems like you're mixing HTTP-requests with UI-logic. IO-ops involving network traffic must not be executed on the UI-Thread. Use `AsyncTask` or the like. – hgoebl May 02 '14 at 16:40
  • @hgoebl The code is a bit deceiving, as this method is actually called from doInBackground() of my AsyncTask and is in a method simply to clean up the code a bit. Thanks again – zgc7009 May 02 '14 at 16:47
  • OK, then you already did it the best way :-), but you could improve your exception handling a bit: call `urlConnection.getResponseCode()` before relying that `getInputStream()` returns the response. In case of `4xx` and `5xx` HTTP status codes, calling getInputStream() throws an exception, you have to call `getErrorStream()` if you're interested in the body of the error response. – hgoebl May 02 '14 at 16:53
  • @hgoebl I get the feeling you have done some http connections in your day :P Thanks very much everything has been extremely helpful – zgc7009 May 02 '14 at 18:11

1 Answers1

6

You have to URL-encode the params, e.g. a space (" ") in a URL is written as "+". Your browser internally does this, probably without showing you the submitted URL.

static String urlEncode(String value) {
    try {
        return URLEncoder.encode(value, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return value;
    }
}

But don't encode the whole URL, only the parameter values. If the parameter names are non-ASCII, they have to be encoded as well, but Google APIs don't use such parameters.

hgoebl
  • 12,637
  • 9
  • 49
  • 72
  • Thank you so much for this, can honestly say I would have never thought of that as I thought those types of conversions would be handled internally. Works like a charm – zgc7009 May 02 '14 at 16:46
  • 1
    And if you want to avoid cumbersome programming HttpURLConnection, you could use [DavidWebb](https://github.com/hgoebl/DavidWebb/blob/master/src/test/java/com/goebl/david/TestWithGoogleApi.java#L48-L57). – hgoebl May 02 '14 at 16:47
  • very nice, looks worth looking into – zgc7009 May 02 '14 at 16:49