Android Maps my-location-layer does not show API > Marshmallow

89 Views Asked by At

Good Evening everybody,

I have a problem with Google Maps SDK on an Android App, I would like to show my-location-layer, I ask permission FINE_LOCATION and COARSE_LOCATION in MainActivity and declare it in Manifest File.

On APi < Marshmallow it's works because, I don't need to accept the permissions but with APi >= Marshmallow it's bad.

I don't see the my_location_layer for the first time when I start the App, I must restart my App for see it.

Below my code, if everyone could help me, thanks.

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.mapsexample">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MapsExample"
        tools:targetApi="31">


        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/maps_api_key" />
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity.java


@SuppressWarnings("all")
public class MainActivity extends AppCompatActivity implements
        GoogleMap.OnMyLocationButtonClickListener,
        GoogleMap.OnMyLocationClickListener,
        OnMapReadyCallback {


    private final int LOCATION_PERMISSION_REQUEST_CODE = 200;

    private String[] PERMISSIONS;

    private SupportMapFragment mapFragment;
    private GoogleMap googleMap;
    private Location currentLocation;
    private FusedLocationProviderClient mFusedLocationClient;


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

        initData();
        checkPermissions();

    }

    private void initData() {

        PERMISSIONS = new String[]{
                Manifest.permission.INTERNET,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
        };

        googleMap = null;
        currentLocation = null;

        mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

    }

    private void checkPermissions() {
        if (hasPermissions(this)) {
            mapFragment.getMapAsync(this);
        } else {
            askLocationPermission();
        }
    }

    private void getLastLocation() {

        Task<Location> locationTask = mFusedLocationClient.getLastLocation();
        locationTask.addOnSuccessListener(new OnSuccessListener<Location>() {
            @Override
            public void onSuccess(Location location) {
                currentLocation = location;
                zoomOnCurrentPlace();
            }
        });
    }


    private void askLocationPermission() {

        if (ActivityCompat.checkSelfPermission(this, PERMISSIONS[1]) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this, PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);
        } else {

            mapFragment.getMapAsync(this);
        }
    }


    private boolean hasPermissions(Context context) {
        if (context != null && PERMISSIONS != null) {

            for (String permission : PERMISSIONS) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }


    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) {

        Toast.makeText(this, "Start OnMapReady", Toast.LENGTH_LONG).show();

        this.googleMap = googleMap;

        this.googleMap.setMapType(this.googleMap.MAP_TYPE_NORMAL);

        this.googleMap.setMyLocationEnabled(true);
        this.googleMap.setOnMyLocationButtonClickListener(this);
        this.googleMap.setOnMyLocationClickListener(this);

        this.googleMap.getUiSettings().setZoomControlsEnabled(true);


        this.googleMap.setOnMapClickListener(latLng -> {
            Toast.makeText(MainActivity.this, "Click on " + latLng, Toast.LENGTH_SHORT).show();

            this.googleMap.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
        });


        getLastLocation();
    }

    private void zoomOnCurrentPlace() {
        LatLng currentPlace = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
        // Move the camera to the this.googleMap coordinates and zoom in closer.
        googleMap.addMarker(new MarkerOptions().position(currentPlace).title("Ma position"));
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentPlace, 17));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {

        boolean permissionsAreAccepted = true;

        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE && grantResults.length > 0) {

            for (int grantResult : grantResults) {
                if (grantResult != PackageManager.PERMISSION_GRANTED) {
                    permissionsAreAccepted = false;
                    break;
                }
            }

            if (permissionsAreAccepted) {
                mapFragment.getMapAsync(this);
            }else {
                askLocationPermission();
            }

        }
    }


    @Override
    public void onMyLocationClick(@NonNull Location location) {
        Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG)
                .show();
    }

    @Override
    public boolean onMyLocationButtonClick() {
        Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT)
                .show();
        return false;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.map_options, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.normal_map:
                googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                return true;
            case R.id.hybrid_map:
                googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                return true;
            case R.id.satellite_map:
                googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                return true;
            case R.id.terrain_map:
                googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Thanks for your help :-)

1

There are 1 best solutions below

0
mabdelouahad On

I solved my problem, just follow, step by step:

  1. create variable type LocationCallback, LocationRequest and long
  private LocationRequest mLocationRequest = null;
  private LocationCallback mLocationCallback = null;
  private final Long LOCATION_REQUEST_INTERVAL = 5000L;
  1. In Oncreate just init your FusedLocationProviderClient, LocationCallback and map
private void initData() {

        PERMISSIONS = new String[]{
                Manifest.permission.INTERNET,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
        };

        googleMap = null;
        currentLocation = null;

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

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

        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(@NonNull LocationResult locationResult) {
                super.onLocationResult(locationResult);
                currentLocation = locationResult.getLastLocation();
            }
        };
    }
  1. In OnCreate call function createLocationRequest
  private void createLocationRequest() {
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(LOCATION_REQUEST_INTERVAL).setFastestInterval(LOCATION_REQUEST_INTERVAL);
//        requestLocationUpdate();
    }
  1. Check your permissions ( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)

  2. if you have permission call getLastLocation() with mFusedLocationClient

  3. In getLastLocation when location != null then googleMap.setLocationSource()

googleMap.setLocationSource(new LocationSource() {
                    @Override
                    public void activate(@NonNull OnLocationChangedListener onLocationChangedListener) {
                        onLocationChangedListener.onLocationChanged(currentLocation);
                        zoomOnCurrentPlace();
                    }

                    @Override
                    public void deactivate() {
                        Toast.makeText(MainActivity.this, "LocationSource deactivated", Toast.LENGTH_SHORT).show();
                    }
                }); 

IF YOU DON'T HAVE PERMISSIONS

  1. If you don't have permission ask them with
private void askLocationPermission() {

        ActivityCompat.requestPermissions(this, PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);
    }
  1. Then in onRequestPermissionsResult if permissions are granted then
  googleMap.setMyLocationEnabled(true);
                requestLocationUpdate();
                getLastLocation();
  1. Elseif just callback askLocationPermission function, don't forgot to create requestLocationUpdate function
 private void requestLocationUpdate() {

        mFusedLocationClient.requestLocationUpdates(
                mLocationRequest,
                mLocationCallback,
                Looper.myLooper()
        );

I Hope it'll help someone :)