我想在我的应用程序中使用 GoogleMap
,但在许多设备上运行该应用程序时,它不会显示空页而不是地图。
主要活动代码:
public class MainActivity extends AppCompatActivity implements RoutingListener, GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
protected GoogleMap map;
protected LatLng start;
protected LatLng end;
@InjectView(R.id.start)
AutoCompleteTextView starting;
@InjectView(R.id.destination)
AutoCompleteTextView destination;
@InjectView(R.id.send)
ImageView send;
private static final String LOG_TAG = "MyActivity";
protected GoogleApiClient mGoogleApiClient;
private PlaceAutoCompleteAdapter mAdapter;
private ProgressDialog progressDialog;
private List<Polyline> polylines;
private static final int[] COLORS = new int[]{R.color.primary_dark,R.color.primary,R.color.primary_light,
R.color.accent, R.color.primary_dark_material_light};
private static final LatLngBounds BOUNDS_JAMAICA= new LatLngBounds(new LatLng(-57.965341647205726, 144.9987719580531),
new LatLng(72.77492067739843, -9.998857788741589));
/**
* This activity loads a map and then displays the route and pushpins on it.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
getSupportActionBar().setDisplayShowHomeEnabled(true);
polylines = new ArrayList<>();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Places.GEO_DATA_API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
MapsInitializer.initialize(this);
mGoogleApiClient.connect();
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.map, mapFragment).commit();
}
map = mapFragment.getMap();
mAdapter = new PlaceAutoCompleteAdapter(this, android.R.layout.simple_list_item_1,
mGoogleApiClient, BOUNDS_JAMAICA, null);
/*
* Updates the bounds being used by the auto complete adapter based on the position of the
* map.
* */
map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {
LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
mAdapter.setBounds(bounds);
}
});
CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(18.013610, -77.498803));
CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
map.moveCamera(center);
map.animateCamera(zoom);
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 5000, 0,
new LocationListener() {
@Override
public void onLocationChanged(Location location) {
CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(),location.getLongitude()));
CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
map.moveCamera(center);
map.animateCamera(zoom);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
});
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
3000, 0, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(),location.getLongitude()));
CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
map.moveCamera(center);
map.animateCamera(zoom);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
});
/*
* Adds auto complete adapter to both auto complete
* text views.
* */
starting.setAdapter(mAdapter);
destination.setAdapter(mAdapter);
/*
* Sets the start and destination points based on the values selected
* from the autocomplete text views.
* */
starting.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final PlaceAutoCompleteAdapter.PlaceAutocomplete item = mAdapter.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i(LOG_TAG, "Autocomplete item selected: " + item.description);
/*
Issue a request to the Places Geo Data API to retrieve a Place object with additional
details about the place.
*/
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
.getPlaceById(mGoogleApiClient, placeId);
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
@Override
public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
// Request did not complete successfully
Log.e(LOG_TAG, "Place query did not complete. Error: " + places.getStatus().toString());
places.release();
return;
}
// Get the Place object from the buffer.
final Place place = places.get(0);
start=place.getLatLng();
}
});
}
});
destination.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final PlaceAutoCompleteAdapter.PlaceAutocomplete item = mAdapter.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i(LOG_TAG, "Autocomplete item selected: " + item.description);
/*
Issue a request to the Places Geo Data API to retrieve a Place object with additional
details about the place.
*/
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
.getPlaceById(mGoogleApiClient, placeId);
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
@Override
public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
// Request did not complete successfully
Log.e(LOG_TAG, "Place query did not complete. Error: " + places.getStatus().toString());
places.release();
return;
}
// Get the Place object from the buffer.
final Place place = places.get(0);
end=place.getLatLng();
}
});
}
});
/*
These text watchers set the start and end points to null because once there's
* a change after a value has been selected from the dropdown
* then the value has to reselected from dropdown to get
* the correct location.
* */
starting.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int startNum, int before, int count) {
if (start != null) {
start = null;
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
destination.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(end!=null)
{
end=null;
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@OnClick(R.id.send)
public void sendRequest()
{
if(Util.Operations.isOnline(this))
{
route();
}
else
{
Toast.makeText(this,"No internet connectivity",Toast.LENGTH_SHORT).show();
}
}
public void route()
{
if(start==null || end==null)
{
if(start==null)
{
if(starting.getText().length()>0)
{
starting.setError("Choose location from dropdown.");
}
else
{
Toast.makeText(this,"Please choose a starting point.",Toast.LENGTH_SHORT).show();
}
}
if(end==null)
{
if(destination.getText().length()>0)
{
destination.setError("Choose location from dropdown.");
}
else
{
Toast.makeText(this,"Please choose a destination.",Toast.LENGTH_SHORT).show();
}
}
}
else
{
progressDialog = ProgressDialog.show(this, "Please wait.",
"Fetching route information.", true);
Routing routing = new Routing.Builder()
.travelMode(AbstractRouting.TravelMode.DRIVING)
.withListener(this)
.alternativeRoutes(true)
.waypoints(start, end)
.build();
routing.execute();
}
}
@Override
public void onRoutingFailure(RouteException e) {
// The Routing request failed
progressDialog.dismiss();
if(e != null) {
Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}else {
Toast.makeText(this, "Something went wrong, Try again", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onRoutingStart() {
// The Routing Request starts
}
@Override
public void onRoutingSuccess(List<Route> route, int shortestRouteIndex)
{
progressDialog.dismiss();
CameraUpdate center = CameraUpdateFactory.newLatLng(start);
CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
map.moveCamera(center);
if(polylines.size()>0) {
for (Polyline poly : polylines) {
poly.remove();
}
}
polylines = new ArrayList<>();
//add route(s) to the map.
for (int i = 0; i <route.size(); i++) {
//In case of more than 5 alternative routes
int colorIndex = i % COLORS.length;
PolylineOptions polyOptions = new PolylineOptions();
polyOptions.color(getResources().getColor(COLORS[colorIndex]));
polyOptions.width(10 + i * 3);
polyOptions.addAll(route.get(i).getPoints());
Polyline polyline = map.addPolyline(polyOptions);
polylines.add(polyline);
Toast.makeText(getApplicationContext(),"Route "+ (i+1) +": distance - "+ route.get(i).getDistanceValue()+": duration - "+ route.get(i).getDurationValue(),Toast.LENGTH_SHORT).show();
}
// Start marker
MarkerOptions options = new MarkerOptions();
options.position(start);
options.icon(BitmapDescriptorFactory.fromResource(R.drawable.start_blue));
map.addMarker(options);
// End marker
options = new MarkerOptions();
options.position(end);
options.icon(BitmapDescriptorFactory.fromResource(R.drawable.end_green));
map.addMarker(options);
}
@Override
public void onRoutingCancelled() {
Log.i(LOG_TAG, "Routing was cancelled.");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.v(LOG_TAG,connectionResult.toString());
}
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
}
}
MainActivity XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v7.widget.CardView
android:id="@+id/cardview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:elevation="100dp"
card_view:cardBackgroundColor="@android:color/white"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<AutoCompleteTextView
android:id="@+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@android:color/transparent"
android:hint="Choose a starting point..." />
<View
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_marginBottom="5dp"
android:layout_marginRight="50dp"
android:layout_marginTop="5dp"
android:background="@drawable/dotted" />
<AutoCompleteTextView
android:id="@+id/destination"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:hint="Choose a destination..." />
</LinearLayout>
<ImageView
android:id="@+id/send"
android:layout_centerVertical="true"
android:layout_marginRight="20dp"
android:layout_alignParentRight="true"
android:layout_width="36dp"
android:src="@drawable/ic_send_grey600_48dp"
android:layout_height="36dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
清单:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.directions.sample" >
<!-- Copied from Google Maps Library/AndroidManifest.xml. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<!-- External storage for caching. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Maps API needs OpenGL ES 2.0. -->
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCXb3CVEfeUQiT7-J-KOvKaqWILPVBkIqg"/>
对于 GeoAPI ,我使用Place API
。
我该如何解决这个问题?
答案 0 :(得分:0)
正如我在您添加的屏幕截图中看到的,看起来已经加载了地图片段(请查看左下角的Google徽标)。由于互联网速度较慢,地图可能需要很长时间才能加载。
答案 1 :(得分:0)
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCXb3CVEfeUQiT7-J-KOvKaqWILPVBkIqg"/>
试试这个:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyCXb3CVEfeUQiT7-J-KOvKaqWILPVBkIqg"/>
注意:如上所示,com.google.android.geo.API_KEY就是 建议的API密钥的元数据名称。具有此名称的密钥可以是 用于在Android上对多个基于Google Maps的API进行身份验证 平台,包括Google Maps Android API。为了倒退 兼容性,API也支持该名称 com.google.android.maps.v2.API_KEY。这个遗留名称允许 仅对Android Maps API v2进行身份验证。应用程序可以 仅指定一个API密钥元数据名称。如果两者都指定, API抛出异常。