我按照these方向尝试使用Google Places API在用户所在位置附近的所有餐馆上显示和添加标记。但是,我收到了这个错误:
12-05 11:23:33.378 1948-2857/com.google.android.gms.persistent W/GLSUser: [AppCertManager] IOException while requesting key:
java.io.IOException: Invalid device key response.
at eyw.a(:com.google.android.gms@11743470:14)
at eyw.a(:com.google.android.gms@11743470:65)
at eyw.a(:com.google.android.gms@11743470:22)
at eyu.a(:com.google.android.gms@11743470:4)
at eyu.onTransact(:com.google.android.gms@11743470:4)
at android.os.Binder.transact(Binder.java:387)
at bvg.onTransact(:com.google.android.gms@11743470:3)
at android.os.Binder.execTransact(Binder.java:453)
我在线搜索了一下,发现它可能与我的API密钥有关,或者我不通过Android应用程序允许某些权限,但我不知道是什么。代码有效,但因为我的密钥无效;它将列表大小(包含地点)返回为0,因此没有标记被绘制到我的应用程序的谷歌地图中。
我目前的代码:
public class FragmentMap extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
private static final int FINE_LOCATION_PERMISSION_REQUEST = 1;
private static final int CONNECTION_RESOLUTION_REQUEST = 2;
private GoogleApiClient mGoogleApiClient;
private GoogleMap mMap;
public boolean permission = false;
Button showLoc;
private double mLat;
private double mLong;
public FragmentMap() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_map, null, false);
SupportMapFragment mapFragment = (SupportMapFragment) this.getChildFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
buildGoogleAPIClient();
showLoc = (Button) rootView.findViewById(R.id.showStore);
showLoc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// hello
if(permission == true){
StringBuilder sbValue = new StringBuilder(sbMethod());
PlacesTask placesTask = new PlacesTask();
placesTask.execute(sbValue.toString());
}
else{
Toast.makeText(getActivity(), "App does not have access to location services.", Toast.LENGTH_SHORT).show();
}
}
});
return rootView;
}
.
.
.
public StringBuilder sbMethod() {
StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("location=" + mLat + "," + mLong);
sb.append("&radius=5000");
sb.append("&types=" + "restaurant");
sb.append("&sensor=true");
sb.append("&key=-My API Key is Here");
Log.d("Map", "api: " + sb.toString());
return sb;
}
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
private class PlacesTask extends AsyncTask<String, Integer, String> {
String data = null;
// Invoked by execute() method of this object
@Override
protected String doInBackground(String... url) {
try {
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
// Executed after the complete execution of doInBackground() method
@Override
protected void onPostExecute(String result) {
ParserTask parserTask = new ParserTask();
// Start parsing the Google places in JSON format
// Invokes the "doInBackground()" method of the class ParserTask
parserTask.execute(result);
}
}
private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String, String>>> {
JSONObject jObject;
// Invoked by execute() method of this object
@Override
protected List<HashMap<String, String>> doInBackground(String... jsonData) {
List<HashMap<String, String>> places = null;
Place_JSON placeJson = new Place_JSON();
try {
jObject = new JSONObject(jsonData[0]);
places = placeJson.parse(jObject);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
return places;
}
// Executed after the complete execution of doInBackground() method
@Override
protected void onPostExecute(List<HashMap<String, String>> list) {
Log.d("Map", "list size: " + list.size());
// Clears all the existing markers;
mMap.clear();
for (int i = 0; i < list.size(); i++) {
// Creating a marker
MarkerOptions markerOptions = new MarkerOptions();
// Getting a place from the places list
HashMap<String, String> hmPlace = list.get(i);
// Getting latitude of the place
double lat = Double.parseDouble(hmPlace.get("lat"));
// Getting longitude of the place
double lng = Double.parseDouble(hmPlace.get("lng"));
// Getting name
String name = hmPlace.get("place_name");
Log.d("Map", "place: " + name);
// Getting vicinity
String vicinity = hmPlace.get("vicinity");
LatLng latLng = new LatLng(lat, lng);
// Setting the position for the marker
markerOptions.position(latLng);
markerOptions.title(name + " : " + vicinity);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
// Placing a marker on the touched position
Marker m = mMap.addMarker(markerOptions);
}
}
}
public class Place_JSON {
/**
* Receives a JSONObject and returns a list
*/
public List<HashMap<String, String>> parse(JSONObject jObject) {
JSONArray jPlaces = null;
try {
/** Retrieves all the elements in the 'places' array */
jPlaces = jObject.getJSONArray("results");
} catch (JSONException e) {
e.printStackTrace();
}
/** Invoking getPlaces with the array of json object
* where each json object represent a place
*/
return getPlaces(jPlaces);
}
private List<HashMap<String, String>> getPlaces(JSONArray jPlaces) {
int placesCount = jPlaces.length();
List<HashMap<String, String>> placesList = new ArrayList<HashMap<String, String>>();
HashMap<String, String> place = null;
/** Taking each place, parses and adds to list object */
for (int i = 0; i < placesCount; i++) {
try {
/** Call getPlace with place JSON object to parse the place */
place = getPlace((JSONObject) jPlaces.get(i));
placesList.add(place);
} catch (JSONException e) {
e.printStackTrace();
}
}
return placesList;
}
/**
* Parsing the Place JSON object
*/
private HashMap<String, String> getPlace(JSONObject jPlace) {
HashMap<String, String> place = new HashMap<String, String>();
String placeName = "-NA-";
String vicinity = "-NA-";
String latitude = "";
String longitude = "";
String reference = "";
try {
// Extracting Place name, if available
if (!jPlace.isNull("name")) {
placeName = jPlace.getString("name");
}
// Extracting Place Vicinity, if available
if (!jPlace.isNull("vicinity")) {
vicinity = jPlace.getString("vicinity");
}
latitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lat");
longitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lng");
reference = jPlace.getString("reference");
place.put("place_name", placeName);
place.put("vicinity", vicinity);
place.put("lat", latitude);
place.put("lng", longitude);
place.put("reference", reference);
} catch (JSONException e) {
e.printStackTrace();
}
return place;
}
}
我在Manifest中添加的相关权限:
<uses-permission android:name="android.permission.INTERNET" />
<permission
android:name="cecs453.android.csulb.edu.recipeapp.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/> //within <application></application>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="-my API Key is pasted here-" /> //within <application></application>
我的gradle中的依赖:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.google.firebase:firebase-auth:11.6.2'
compile 'com.loopj.android:android-async-http:1.4.9'
testCompile 'junit:junit:4.12'
compile 'com.android.support:recyclerview-v7:26.+'
compile 'com.android.support:cardview-v7:26.+'
compile 'com.android.support:design:26.1.0'
implementation 'com.google.android.gms:play-services-maps:11.6.2'
compile 'com.google.android.gms:play-services:11.6.2'
compile 'com.google.android.gms:play-services-places:11.6.2'
compile "com.google.android.gms:play-services-location:11.6.2"
}