android - Mostrar ubicación actual dentro del fragmento de mapa de Google
google-maps maps (2)
Esto es similar a mi otra respuesta aquí , sin embargo, esto es diferente debido al hecho de que está extendiendo el MapFragment y tiene su comportamiento personalizado implementado dentro del Fragment.
Aquí hay un Fragmento de ejemplo que extiende SupportMapFragment, al iniciarse obtendrá la ubicación actual del usuario, colocará un Marcador y acercará:
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
}
}
}
Dado que la solicitud de permiso de ubicación debe pasar por la Actividad, deberá enrutar el resultado de la Actividad al método
onRequestPermissionsResult()
del Fragmento:
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);
}
}
}
El diseño solo contiene un FrameLayout donde va el 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>
Resultado
Primer mensaje para el permiso de ubicación:
Una vez que se otorga el permiso de Ubicación, muestre la ubicación actual con un Marcador:
Si el usuario alguna vez niega o revoca el permiso de Ubicación, esto se mostrará al iniciar la aplicación:
Primero, la explicación:
Luego, la solicitud de permiso de ubicación:
Actualmente estoy trabajando en un Fragmento con un Mapa de Google en él. Una vez que un usuario visita ese fragmento, su mapa debe hacer zoom y enfocarse en su ubicación. Sin embargo, muestra el mapa del mundo y no la ubicación cercana (usuario cercano):
@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) {
}
}
¿Hay una función de zoom disponible? También mi API me permite acceder al código postal del usuario. ¿Puedo usar eso en su lugar? Requiero que se muestren al usuario sus ubicaciones cercanas.
Lo sentimos, pero eso es demasiado (arriba), corto y rápido , si tiene el MapFragment, también tiene que hacer un mapa, solo haga lo siguiente:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
googleMap.setMyLocationEnabled(true)
} else {
// Show rationale and request permission.
}
el zoom funciona así:
val cameraPosition = CameraPosition.Builder().target(LatLng(location.latitude, location.longitude)).zoom(17.0.toFloat()).build()
val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
googleMap?.moveCamera(cameraUpdate)
El código está en Kotlin , espero que no te importe. 17.0f es un nivel de zoom bastante detallado. Solo prueba diferentes valores.
que te diviertas