nexus_2006
nexus_2006

Reputation: 754

Places API returns REQUEST_DENIED

I know there are a million threads on this, but I searched many of them with no help, I promise.

I am trying to use Places API to return results. I have tried the following:

Ensure a valid key (it works in this same app where I use a mapFragment, so I know the key is good. The places api was enabled at the time the key was generated.). In addition, I generated a new key and updated the app, map still works.

Make sure the search URL is formed correctly. I copied and pasted from the log into the browser, subbing the browser key, and the results returned appropriately.

Here is the manifest:

<permission
    android:name="com.example.mapdemo.permission.MAPS_RECEIVE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.example.mapdemo.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.berrmal.locationbox.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <meta-data
        android:name="com.google.android.maps.v2.API_KEY"
        android:value="AIza**********************************Y" />

    <service
        android:name="com.berrmal.locationbox.LocationBoxService"
        android:enabled="true"
        android:exported="false" >
    </service>
</application>

Here is the AsyncTask:

public class PlacesProvider extends AsyncTask<String, Void, ArrayList<Place>> {
    //starting arg, progress update type, return from doInBack()
    public PlacesProvider() {

    }

    public ArrayList<Place> doInBackground(String... args) {
        //args[0] = search URL
        Log.d("lbServ","doing in background");
        ArrayList<Place> resultList = new ArrayList<Place>();
        DLJSON dLJSON = new DLJSON();
        try {
            resultList = dLJSON.getResults(args[0]);
        } catch (UnsupportedEncodingException uee) {
            Log.d("lbServ","unsupp encode ex");
        } catch (IOException ioe) {
            Log.d("lbServ","IO exception");
        } catch (IllegalStateException ils) {
            Log.d("lbserv","iill state exception");
            ils.printStackTrace();
        } catch (Exception ex) {
            Log.d("lbServ", "unknown exception in dlJson");
        }
        if (resultList == null) {
            Log.d("lbServ","resultList is null");
        }
        return resultList;
    }

    protected void onPostExecute(ArrayList<Place> result) {
        Log.d("lbServ","onnPostExecute");
        placesList = result;
        //TODO do something with the result, i.e. send it to MainActivity via instance that bound to server
        Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
        //resultIntent.setComponent(new ComponentName("com.berrmal.locationbox", "MainActivity"));
        resultIntent.putExtra("SearchSuccess", true);
        resultIntent.putExtra("searchID", 1);
        resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getApplication().startActivity(resultIntent);
        Log.d("lbServ","service suicide");
        stopSelf();
    }

And the JSON querier/parser

public ArrayList<Place> getResults(String searchURL) throws UnsupportedEncodingException, IOException, IllegalStateException{
    try {
        url = new URL(searchURL);
        Log.d("lbDLJSON",url.toString());
    } catch (Exception ex) {
        Log.d("lbDLJSON", "malformed URL");
    }

    try {
            urlConn = (HttpsURLConnection) url.openConnection();
            Log.d("dlJson","url connection open");
            is = new BufferedInputStream(urlConn.getInputStream());
            Log.d("dljson","buffered stream open");
    } catch (IOException ioe) {
            Log.d("lbDLJSON", "io exception");
    } catch (Exception e) {
        Log.d("lbDLJSON", "that other exception");
    } 
    jsonReader = new JsonReader(new InputStreamReader(is, "UTF-8"));
    Log.d("lbjson","json and inputstream readers exists");
    resultList = new ArrayList<Place>();
    jsonReader.beginObject();
    Log.d("lbjson", "top level object open");
    while (jsonReader.hasNext()) {
        String name = jsonReader.nextName().toString();
        if (name.equals("results")) {
            jsonReader.beginArray();
            while (jsonReader.hasNext()); {
                //resultList.add(placeBuilder(jsonReader));
                Log.d("lbjson", "results were null");
            }
            jsonReader.endArray();
        } else if (name.equals("status")){
            statusCode = jsonReader.nextString().toString();
            Log.d("dljson", "status code: " + statusCode);
        } else {
            Log.d("lbjson", "skipped " + name);
            jsonReader.skipValue();
        }

    }
    jsonReader.endObject();
    Log.d("lbDLJSON", "top level JSON object closed");
    jsonReader.close();
    urlConn.disconnect();

    return resultList;
    //Log.d("lbjson", "");

}

LogCat output:

05-24 16:04:07.859: D/lbServ(19523): search
05-24 16:04:07.859: D/lbServ(19523): executeAsyncTask
05-24 16:04:07.859: D/lbServ(19523): doing in background
05-24 16:04:07.859: D/lbDLJSON(19523): https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=AIza***************************Y&location=34.0937751,-117.6730797&radius=15000&sensor=true&keyword=food
05-24 16:04:07.859: D/dlJson(19523): url connection open
05-24 16:04:08.199: D/dljson(19523): buffered stream open
05-24 16:04:08.199: D/lbjson(19523): json and inputstream readers exists
05-24 16:04:08.199: D/lbjson(19523): top level object open
05-24 16:04:08.199: D/lbjson(19523): skipped html_attributions
05-24 16:04:08.199: D/lbjson(19523): results were null
05-24 16:04:08.199: D/dljson(19523): status code: REQUEST_DENIED
05-24 16:04:08.199: D/lbDLJSON(19523): top level JSON object closed
05-24 16:04:08.199: D/lbServ(19523): onnPostExecute
05-24 16:04:08.220: D/lbServ(19523): service suicide

I can post the URL generating method, but as you see the URL is formed appropriately from the log.

I have been googling and trying things for several hours, so I'm really stumped. I don't understand why I can paste the same link into the browser, change the key to the browser key, and get valid results (8.3kb), but the app here returns the following 85b result:

{
"html_attributions" : [],
"results" : [],
"status" : "REQUEST_DENIED"
}

I get this same request denied result when clicking the "try it out!" link on the api console list of services, but if I make the URL manually I get valid results...?

EDIT:

I kept the android app key in the manifest, for maps permission, but in the HTTP request, I changed the key to the browser key, and got successful results on the places query. I don't know why, it doesn't really make sense. I'm a bit afraid that its a breach of the TOS, but I'm not really sure. Is this indicative of something I'm doing wrong? Or does anyone know a way to contact Google to report it? Or was I supposed to use both keys all along?

Upvotes: 2

Views: 942

Answers (1)

nexus_2006
nexus_2006

Reputation: 754

OK, as best I can tell, the issue was solved by using both keys. I use the Android API key in my manifest, this gets the mapFragment working correctly.

To get the places request to come back "OK" and not "REQUEST_DENIED", I had to use the browser key from the Google API console. I assume, because my app constructs a search URL and uses the HTTP connection to send and receive, google's server thinks its a browser rather than an app. I don't know if this is correct usage, if I get a nastygram from Google I'll update the thread.

Upvotes: 1

Related Questions