显示Google Map Fragment中的当前位置

我目前正在研究一个带有Google Map的Fragment。 一旦用户访问该片段,他的地图应该放大并聚焦在他的位置上。 但是,它显示的是世界地图而不是附近的位置(靠近用户):

@SuppressWarnings("unused") public class DeferredMapFragment extends MapFragment implements GoogleMap.OnCameraChangeListener, OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { private static final String TAG = "DeferredMapFragment"; private Deque<Runnable> pendingActions; private AbstractMap<Marker, Object> tags; private GoogleMap map; private LocationRequest mLocationRequest; private GoogleApiClient mGoogleApiClient; private Location mLastLocation; private Marker marker; private GoogleMap.OnCameraChangeListener cameraChangeListener = null; private boolean isMapReady = false; /* * INTERNALS */ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (getMap() != null) { map = getMap(); getMap().setOnCameraChangeListener(this); } } @Override public void onCameraChange(CameraPosition cameraPosition) { isMapReady = true; if (pendingActions != null) { int i = pendingActions.size(); while (i > 0) { pendingActions.pop().run(); --i; } } if (cameraChangeListener != null) { cameraChangeListener.onCameraChange(cameraPosition); } if (getMap() != null) { getMap().setOnCameraChangeListener(cameraChangeListener); } } private void execute(Runnable action) { if (action == null) { return; } if (isMapReady) { action.run(); } else { if (pendingActions == null) { pendingActions = new LinkedList<>(); } pendingActions.add(action); } } /* * TAGGING */ private void addTag(Marker key, Object value) { if (tags == null) { tags = new HashMap<>(); } tags.put(key, value); } public Object getTag(Marker key) { return tags != null ? tags.get(key) : null; } /* * LISTENERS */ public void setOnInfoWindowClickListener(final GoogleMap.OnInfoWindowClickListener listener) { execute(new Runnable() { @Override public void run() { getMap().setOnInfoWindowClickListener(listener); } }); } public void setOnCameraChangeListener(final GoogleMap.OnCameraChangeListener listener) { cameraChangeListener = listener; } public void setOnMarkerClickListener(final GoogleMap.OnMarkerClickListener listener) { execute(new Runnable() { @Override public void run() { getMap().setOnMarkerClickListener(listener); } }); } public void setOnMapClickListener(final GoogleMap.OnMapClickListener listener) { execute(new Runnable() { @Override public void run() { getMap().setOnMapClickListener(listener); } }); } /* * MAP OVERLAYS */ public void addPolyline(final PolylineOptions options) { execute(new Runnable() { @Override public void run() { getMap().addPolyline(options); } }); } public void addPolygon(final PolygonOptions options) { execute(new Runnable() { @Override public void run() { getMap().addPolygon(options); } }); } public void addCircle(final CircleOptions options) { execute(new Runnable() { @Override public void run() { getMap().addCircle(options); } }); } public void addMarker(final MarkerOptions options) { addMarker(options, null); } public void addMarker(final MarkerOptions options, final Object tag) { execute(new Runnable() { @Override public void run() { Marker marker = getMap().addMarker(options); if (tag != null) { addTag(marker, tag); } } }); } public void addGroundOverlay(final GroundOverlayOptions options) { execute(new Runnable() { @Override public void run() { getMap().addGroundOverlay(options); } }); } public void addTileOverlay(final TileOverlayOptions options) { execute(new Runnable() { @Override public void run() { getMap().addTileOverlay(options); } }); } /* * UI SETTINGS */ public void setMapToolbarEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setMapToolbarEnabled(enabled); } }); } public void setPadding(final int left, final int top, final int right, final int bottom) { execute(new Runnable() { @Override public void run() { getMap().setPadding(left, top, right, bottom); } }); } public void setZoomControlsEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setZoomControlsEnabled(enabled); } }); } public void setCompassEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setCompassEnabled(enabled); } }); } public void setMyLocationButtonEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setMyLocationButtonEnabled(enabled); } }); } public void setIndoorLevelPickerEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setIndoorLevelPickerEnabled(enabled); } }); } public void setScrollGesturesEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setScrollGesturesEnabled(enabled); } }); } public void setZoomGesturesEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setZoomGesturesEnabled(enabled); } }); } public void setTiltGesturesEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setTiltGesturesEnabled(enabled); } }); } public void setRotateGesturesEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setRotateGesturesEnabled(enabled); } }); } public void setAllGesturesEnabled(final boolean enabled) { execute(new Runnable() { @Override public void run() { getMap().getUiSettings().setAllGesturesEnabled(enabled); } }); } public void setInfoWindowAdapter(final GoogleMap.InfoWindowAdapter adapter) { execute(new Runnable() { @Override public void run() { getMap().setInfoWindowAdapter(adapter); } }); } @Override public void onMapReady(GoogleMap googleMap) { map = googleMap; setUpMap(); } public void setUpMap() { map.setMapType(GoogleMap.MAP_TYPE_HYBRID); if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } map.setMyLocationEnabled(true); } @Override public void onConnected(Bundle bundle) { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(1000); mLocationRequest.setFastestInterval(1000); mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); //mLocationRequest.setSmallestDisplacement(0.1F); if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } @Override public void onConnectionSuspended(int i) { } @Override public void onLocationChanged(Location location) { mLastLocation = location; //remove previous current location Marker if (marker != null){ marker.remove(); } double dLatitude = mLastLocation.getLatitude(); double dLongitude = mLastLocation.getLongitude(); marker = map.addMarker(new MarkerOptions().position(new LatLng(dLatitude, dLongitude)) .title("My Location").icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_RED))); map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(dLatitude, dLongitude), 8)); } @Override public void onPause() { super.onPause(); if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } } protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(getContext()) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } } 

是否有缩放function? 我的API也允许我访问用户的邮政编码。 我可以用它来代替吗? 我要求用户在附近的位置显示。

这与我在这里的其他答案类似,但是,这是不同的,因为你扩展了MapFragment,并在Fragment中实现了自定义行为。

下面是一个扩展了SupportMapFragment的片段的例子,在启动的时候它将得到用户的当前位置,放置一个标记,然后放大:

 public class MapFragment extends SupportMapFragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { GoogleMap mGoogleMap; SupportMapFragment mapFrag; LocationRequest mLocationRequest; GoogleApiClient mGoogleApiClient; Location mLastLocation; Marker mCurrLocationMarker; @Override public void onResume() { super.onResume(); setUpMapIfNeeded(); } private void setUpMapIfNeeded() { if (mGoogleMap == null) { getMapAsync(this); } } @Override public void onPause() { super.onPause(); //stop location updates when Activity is no longer active if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } } @Override public void onMapReady(GoogleMap googleMap) { mGoogleMap=googleMap; mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); //Initialize Google Play Services if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { //Location Permission already granted buildGoogleApiClient(); mGoogleMap.setMyLocationEnabled(true); } else { //Request Location Permission checkLocationPermission(); } } else { buildGoogleApiClient(); mGoogleMap.setMyLocationEnabled(true); } } protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); mGoogleApiClient.connect(); } @Override public void onConnected(Bundle bundle) { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(1000); mLocationRequest.setFastestInterval(1000); mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } } @Override public void onConnectionSuspended(int i) {} @Override public void onConnectionFailed(ConnectionResult connectionResult) {} @Override public void onLocationChanged(Location location) { mLastLocation = location; if (mCurrLocationMarker != null) { mCurrLocationMarker.remove(); } //Place current location marker LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latLng); markerOptions.title("Current Position"); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); mCurrLocationMarker = mGoogleMap.addMarker(markerOptions); //move map camera mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,11)); } public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99; private void checkLocationPermission() { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) { // Show an explanation to the user *asynchronously* -- don't block // this thread waiting for the user's response! After the user // sees the explanation, try again to request the permission. new AlertDialog.Builder(getActivity()) .setTitle("Location Permission Needed") .setMessage("This app needs the Location permission, please accept to use location functionality") .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //Prompt the user once explanation has been shown ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION ); } }) .create() .show(); } else { // No explanation needed, we can request the permission. ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION ); } } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_LOCATION: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // location-related task you need to do. if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (mGoogleApiClient == null) { buildGoogleApiClient(); } mGoogleMap.setMyLocationEnabled(true); } } else { // permission denied, boo! Disable the // functionality that depends on this permission. Toast.makeText(getActivity(), "permission denied", Toast.LENGTH_LONG).show(); } return; } // other 'case' lines to check for other // permissions this app might request } } } 

由于“位置”权限请求需要经过“活动”,因此您需要将活动的结果路由到片段的onRequestPermissionsResult()方法:

 public class MainActivity extends AppCompatActivity { MapFragment mapFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mapFragment = new MapFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.mapframe, mapFragment); transaction.commit(); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { if (requestCode == MapFragment.MY_PERMISSIONS_REQUEST_LOCATION){ mapFragment.onRequestPermissionsResult(requestCode, permissions, grantResults); } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } } 

该布局只包含一个FrameLayout,在MapFragment中进行。

activity_main.xml中:

 <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.danielnugent.mapapplication.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/mapframe" android:layout_marginTop="?attr/actionBarSize" android:layout_height="match_parent" android:layout_width="match_parent" /> </android.support.design.widget.CoordinatorLayout> 

结果

首先提示“位置”权限:

在这里输入图像描述

一旦授予位置权限,用标记显示当前位置:

在这里输入图像描述

如果用户曾拒绝或撤销位置权限,则会在应用启动时显示:

一,解释:

在这里输入图像描述

然后,位置权限请求:

在这里输入图像描述