title: Places API returns REQUEST_DENIED
body: <p>I know there are a million threads on this, but I searched many of them with no help, I promise.</p>
  
  <p>I am trying to use Places API to return results.  I have tried the following:</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>Here is the manifest:</p>
  
  <pre><code>&lt;permission
      android:name="com.example.mapdemo.permission.MAPS_RECEIVE"
      android:protectionLevel="signature" /&gt;
  
  &lt;uses-permission android:name="com.example.mapdemo.permission.MAPS_RECEIVE" /&gt;
  &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
  &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
  &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
  &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
  &lt;uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /&gt;
  
  &lt;uses-feature
      android:glEsVersion="0x00020000"
      android:required="true" /&gt;
  
  &lt;application
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" &gt;
      &lt;activity
          android:name="com.berrmal.locationbox.MainActivity"
          android:label="@string/app_name" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.MAIN" /&gt;
  
              &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
  
      &lt;meta-data
          android:name="com.google.android.maps.v2.API_KEY"
          android:value="AIza**********************************Y" /&gt;
  
      &lt;service
          android:name="com.berrmal.locationbox.LocationBoxService"
          android:enabled="true"
          android:exported="false" &gt;
      &lt;/service&gt;
  &lt;/application&gt;
  </code></pre>
  
  <p>Here is the AsyncTask:</p>
  
  <pre><code>public class PlacesProvider extends AsyncTask&lt;String, Void, ArrayList&lt;Place&gt;&gt; {
      //starting arg, progress update type, return from doInBack()
      public PlacesProvider() {
  
      }
  
      public ArrayList&lt;Place&gt; doInBackground(String... args) {
          //args[0] = search URL
          Log.d("lbServ","doing in background");
          ArrayList&lt;Place&gt; resultList = new ArrayList&lt;Place&gt;();
          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&lt;Place&gt; 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();
      }
  </code></pre>
  
  <p>And the JSON querier/parser</p>
  
  <pre><code>public ArrayList&lt;Place&gt; 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&lt;Place&gt;();
      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", "");
  
  }
  </code></pre>
  
  <p>LogCat output:</p>
  
  <pre><code>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&amp;location=34.0937751,-117.6730797&amp;radius=15000&amp;sensor=true&amp;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
  </code></pre>
  
  <p>I can post the URL generating method, but as you see the URL is formed appropriately from the log.</p>
  
  <p>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:</p>
  
  <pre><code>{
  "html_attributions" : [],
  "results" : [],
  "status" : "REQUEST_DENIED"
  }
  </code></pre>
  
  <p>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...?</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>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?</p>