How can I show current location on a Google Map on Android Marshmallow?

后端 未结 3 1269
夕颜
夕颜 2020-11-21 22:56

I want google maps to show the location of the user. I tried this code, but it did not work on Android 6.

private GoogleMap map;
LocationManager lm;
Location         


        
相关标签:
3条回答
  • 2020-11-21 22:58

    For using FusedLocationProviderClient with Google Play Services 11 and higher:

    see here: How to get current Location in GoogleMap using FusedLocationProviderClient

    For using (now deprecated) FusedLocationProviderApi:

    If your project uses Google Play Services 10 or lower, using the FusedLocationProviderApi is the optimal choice.

    The FusedLocationProviderApi offers less battery drain than the old open source LocationManager API. Also, if you're already using Google Play Services for Google Maps, there's no reason not to use it.

    Here is a full Activity class that places a Marker at the current location, and also moves the camera to the current position.

    It also checks for the Location permission at runtime for Android 6 and later (Marshmallow, Nougat, Oreo). In order to properly handle the Location permission runtime check that is necessary on Android M/Android 6 and later, you need to ensure that the user has granted your app the Location permission before calling mGoogleMap.setMyLocationEnabled(true) and also before requesting location updates.

    public class MapLocationActivity extends AppCompatActivity
            implements OnMapReadyCallback,
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener,
            LocationListener {
    
        GoogleMap mGoogleMap;
        SupportMapFragment mapFrag;
        LocationRequest mLocationRequest;
        GoogleApiClient mGoogleApiClient;
        Location mLastLocation;
        Marker mCurrLocationMarker;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            getSupportActionBar().setTitle("Map Location Activity");
    
            mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            mapFrag.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(this,
                        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(this)
                    .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(this,
                    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(this, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
    
                // Should we show an explanation?
                if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                        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(this)
                            .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(MapLocationActivity.this,
                                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                            MY_PERMISSIONS_REQUEST_LOCATION );
                                }
                            })
                            .create()
                            .show();
    
    
                } else {
                    // No explanation needed, we can request the permission.
                    ActivityCompat.requestPermissions(this,
                            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(this,
                                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(this, "permission denied", Toast.LENGTH_LONG).show();
                    }
                    return;
                }
    
                // other 'case' lines to check for other
                // permissions this app might request
            }
        }
    
    }
    

    activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <fragment xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:map="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/map"
            tools:context=".MapLocationActivity"
            android:name="com.google.android.gms.maps.SupportMapFragment"/>
    
    </LinearLayout>
    

    Result:

    Show permission explanation if needed using an AlertDialog (this happens if the user denies a permission request, or grants the permission and then later revokes it in the settings):

    Prompt the user for Location permission by calling ActivityCompat.requestPermissions():

    Move camera to current location and place Marker when the Location permission is granted:

    0 讨论(0)
  • 2020-11-21 23:09

    Sorry but that's just much too much overhead (above), short and quick, if you have the MapFragment, you also have to map, just do the following:

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                googleMap.setMyLocationEnabled(true)
    } else {
        // Show rationale and request permission.
    }
    

    Code is in Kotlin, hope you don't mind.

    have fun

    Btw I think this one is a duplicate of: Show Current Location inside Google Map Fragment

    0 讨论(0)
  • 2020-11-21 23:22

    Firstly make sure your API Key is valid and add this into your manifest <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    Here's my maps activity.. there might be some redundant information in it since it's from a larger project I created.

    import android.content.Intent;
    import android.content.IntentSender;
    import android.location.Location;
    import android.support.v4.app.FragmentActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    
    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.location.LocationListener;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;
    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.OnMapReadyCallback;
    import com.google.android.gms.maps.SupportMapFragment;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.Marker;
    import com.google.android.gms.maps.model.MarkerOptions;
    
    public class MapsActivity extends FragmentActivity implements
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener,
            LocationListener {
    
    
        //These variable are initalized here as they need to be used in more than one methid
        private double currentLatitude; //lat of user
        private double currentLongitude; //long of user
    
        private double latitudeVillageApartmets= 53.385952001750184;
        private double longitudeVillageApartments= -6.599087119102478;
    
    
        public static final String TAG = MapsActivity.class.getSimpleName();
    
        private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
    
        private GoogleMap mMap; // Might be null if Google Play services APK is not available.
    
        private GoogleApiClient mGoogleApiClient;
        private LocationRequest mLocationRequest;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_maps);
            setUpMapIfNeeded();
    
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
    
            // Create the LocationRequest object
            mLocationRequest = LocationRequest.create()
                    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                    .setInterval(10 * 1000)        // 10 seconds, in milliseconds
                    .setFastestInterval(1 * 1000); // 1 second, in milliseconds
     }
        /*These methods all have to do with the map and wht happens if the activity is paused etc*/
        //contains lat and lon of another marker
        private void setUpMap() {
    
                MarkerOptions marker = new MarkerOptions().position(new LatLng(latitudeVillageApartmets, longitudeVillageApartments)).title("1"); //create marker
                mMap.addMarker(marker); // adding marker
        }
    
        //contains your lat and lon
        private void handleNewLocation(Location location) {
            Log.d(TAG, location.toString());
    
            currentLatitude = location.getLatitude();
            currentLongitude = location.getLongitude();
    
            LatLng latLng = new LatLng(currentLatitude, currentLongitude);
    
            MarkerOptions options = new MarkerOptions()
                    .position(latLng)
                    .title("You are here");
            mMap.addMarker(options);
            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom((latLng), 11.0F));
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            setUpMapIfNeeded();
            mGoogleApiClient.connect();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
    
            if (mGoogleApiClient.isConnected()) {
                LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
                mGoogleApiClient.disconnect();
            }
        }
    
        private void setUpMapIfNeeded() {
            // Do a null check to confirm that we have not already instantiated the map.
            if (mMap == null) {
                // Try to obtain the map from the SupportMapFragment.
                mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                        .getMap();
                // Check if we were successful in obtaining the map.
                if (mMap != null) {
                    setUpMap();
                }
    
            }
        }
    
        @Override
        public void onConnected(Bundle bundle) {
            Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            if (location == null) {
                LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            }
            else {
                handleNewLocation(location);
            }
        }
    
        @Override
        public void onConnectionSuspended(int i) {
        }
    
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            if (connectionResult.hasResolution()) {
                try {
                    // Start an Activity that tries to resolve the error
                    connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
                    /*
                     * Thrown if Google Play services canceled the original
                     * PendingIntent
                     */
                } catch (IntentSender.SendIntentException e) {
                    // Log the error
                    e.printStackTrace();
                }
            } else {
                /*
                 * If no resolution is available, display a dialog to the
                 * user with the error.
                 */
                Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
            }
        }
    
        @Override
        public void onLocationChanged(Location location) {
            handleNewLocation(location);
        }
    
    }
    

    There's a lot of methods here that are hard to understand but basically all update the map when it's paused etc. There are also connection timeouts etc. Sorry for just posting this, I tried to fix your code but I couldn't figure out what was wrong.

    0 讨论(0)
提交回复
热议问题