14

I was using LocationManager to track the user current location, Now after changing location manager to FusedLocation API, the blue dot and circle is not shown even after setting map.setMyLocationEnabled(true). I can see the current location icon on top right corner in my map fragment but clicking on it does nothing. I reverted my code to LocationManager now i am able to see the blue dot pointing to my current location. what could be wrong using Fused Location API.

flexdroid
  • 8,437
  • 2
  • 21
  • 27
  • Regarding the `MyLocation` button, it shouldn't matter what you use. You don't have to add any code at all for that button and the blue mark to work. – Daniel Nugent May 15 '15 at 06:53
  • @DanielNugent, But click is not working on MyLocation button on top right corner and I am not seeing the blue circle pointer on my current location. – flexdroid May 15 '15 at 06:58
  • 1
    That is strange. Can you show some of your code? Are you using a `SupportMapFragment`? – Daniel Nugent May 15 '15 at 07:00
  • 2
    Yes, I am using `SupportMapFragment` – flexdroid May 15 '15 at 07:07
  • 1
    I just started a new blank project in Android Studio, and the only code I had to add was this: `mFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); map = mFragment.getMap(); map.setMyLocationEnabled(true);` – Daniel Nugent May 15 '15 at 07:21
  • To get current user location are you using android FusedLocation API ? – flexdroid May 15 '15 at 07:36
  • For the `MyLocation` button, and blue dot, it doesn't really have anything to do with getting the current location in the code, since the map does all the work for that. – Daniel Nugent May 15 '15 at 07:46
  • Thats true but when used FusedLocationApi to get user current location the blue dot disappears and the MyLocation button does not work. Try this `https://developer.android.com/training/location/receive-location-updates.html` in the same example project you created and `onLocationChanged()` method point the marker to current location. – flexdroid May 15 '15 at 07:58

3 Answers3

29

For targeting api-23 or higher

See this answer....

For targeting api-22 and lower:

This code works for me, it has the MyLocation blue dot/circle, and it also places a Marker on the current location using the Fused Location Provider.

Here is the entire Activity code I used:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import android.location.Location;
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.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.OnMapReadyCallback;

public class MainActivity extends AppCompatActivity implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        OnMapReadyCallback {

    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;

    LatLng latLng;
    GoogleMap mGoogleMap;
    SupportMapFragment mFragment;
    Marker mCurrLocation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        mGoogleMap = googleMap;

        mGoogleMap.setMyLocationEnabled(true);

        buildGoogleApiClient();

        mGoogleApiClient.connect();
    }

    @Override
    public void onPause() {
        super.onPause();
        //Unregister for location callbacks:
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();
        Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            //place marker at current position
            mGoogleMap.clear();
            latLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(latLng);
            markerOptions.title("Current Position");
            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
            mCurrLocation = mGoogleMap.addMarker(markerOptions);
        }

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000); //5 seconds
        mLocationRequest.setFastestInterval(3000); //3 seconds
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        //mLocationRequest.setSmallestDisplacement(0.1F); //1/10 meter

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int i) {
        Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLocationChanged(Location location) {

        //remove previous current location marker and add new one at current position
        if (mCurrLocation != null) {
            mCurrLocation.remove();
        }
        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));
        mCurrLocation = mGoogleMap.addMarker(markerOptions);

        Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show();

        //If you only need one location, unregister the listener
        //LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }

}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <fragment
        class="com.google.android.gms.maps.SupportMapFragment"
        android:id="@+id/map"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</RelativeLayout>

Result:

MyLocationPlusFusedLocationProvider

Community
  • 1
  • 1
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • This worked for me. However, I need to use the location stored in the LatLang object. When I try to access them, I get a null pointer exception. Any ideas? – gabbar0x Nov 30 '15 at 01:59
  • @bholagabbar If you need to you can store a reference to the current Location object returned in `onLocationChanged()`, which this code does using a LatLng. Be sure to check that it's not null whenever you use it, since a location might not have come in yet. Anything that depends on a location lock, kick it off in onLocationChanged() if need be. – Daniel Nugent Nov 30 '15 at 02:04
  • I tried making latLang gloabl, but i still get nullpointerException. I didn't understand your way. Could you just elaborate? – gabbar0x Nov 30 '15 at 02:51
  • @bholagabbar The LatLng object will be null before the first location callback `onLocationChanged()` is called, and then non-null after. If you try to access `latLng` in `onCreate()` it won't work, because it hasn't gotten into `onLocationChanged()` yet. – Daniel Nugent Nov 30 '15 at 02:58
  • it gave me error: `java.lang.SecurityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.` but I have setup permissions in manifests `` – Muhammad Shahzad Dec 19 '15 at 17:33
  • 1
    @MuhammadShahzad Are you testing on Android M (Android 6)? If so, you will need to prompt the user at runtime, see here: http://stackoverflow.com/questions/33063712/security-exception-only-on-android-6 – Daniel Nugent Dec 19 '15 at 17:35
  • Yes I'm testing on Android 6 – Muhammad Shahzad Dec 19 '15 at 17:56
  • @Daniel There is a problem in your solution. If onStart gets called Before onMapready, the Google client will never call connect – Johny19 Aug 17 '16 at 11:25
  • @johny there is no onStart() in this answer.... it sounds like you just need to move some code from onStart() into onMapReady(). What do you have in your onStart() code? – Daniel Nugent Aug 17 '16 at 13:43
  • Yea forget what I said, I mixed :/ with an other example – Johny19 Aug 17 '16 at 17:50
  • @Johny19 Ahh, no prob! – Daniel Nugent Aug 17 '16 at 18:09
  • @Daniel Nugent: can you tell me how to reduce the radius of that blue circle which is wide ,more specifically I want to reduce the circle so that I can get high accuracy – Pratik Vyas Oct 11 '18 at 14:10
  • @PratikVyas That blue circle comes from the framework, and it's based on the accuracy of the location that it currently has. I don't think there's a way to reduce the blue circle in app code. Basically, the framework just needs to get a location lock with better accuracy. – Daniel Nugent Oct 11 '18 at 17:34
  • @DanielNugent : Thanks for quick reply, can we prompt a user that it has good accuracy or bad accuracy using getAccuracy method of location manager, if so what will be identical value to be chacked during check – Pratik Vyas Oct 12 '18 at 07:50
6

You have to add the following permissions in manifest:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />
  • 1
    Wow... Thank you @MuhammadMoosa! I spent so much time trying to figure out why my location is not accurate in one app, WHILE when I debug my other app it was perfect... I checked permissions many times and the only one I was missing was ``. I didn't even think that this permission is related to maps anyhow.. – chabislav Apr 29 '16 at 11:57
  • Actually you only need one. Either ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION, depending on your implementation. – mayid May 17 '20 at 15:50
1
MarkerOptions().position(new LatLng(
                            location.getLatitude(), location.getLongitude()));

Try this,

   if (location!=null) {
                googleMap.clear();
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());

                CameraPosition cameraPosition = new CameraPosition.Builder()
                        .target(new LatLng(location.getLatitude(), location.getLongitude())).zoom(14).build();
                googleMap.animateCamera(CameraUpdateFactory
                        .newCameraPosition(cameraPosition));

                // create markerOptions
                MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(
                        location.getLatitude(), location.getLongitude()));
                // ROSE color icon
                markerOptions.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
                markerOptions.position(latLng);
                // adding markerOptions
                Marker marker = googleMap.addMarker(markerOptions);
                dropPinEffect(marker);
            }
Ashish Dwivedi
  • 8,048
  • 5
  • 58
  • 78