I can't find my current location button in Android Marshmallow. I am using google map api.
I have already enabled these:
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
I have tried in jellybean, lollipop and it is working fine but I can't find this button and my current location marker in Marshmallow.
Why is this happening and how can I fix it?
Got the solution for my problem:
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Mumbai.getCenter(), 11));
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Related
I am trying to ask for user location permission but I need to set some kind of listener to the user response otherwise, I cant get the user location and the app crashes due to null pointer exception.
This are the functions I am using to get and set the location
private void setLocation() {
if (ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, 44);
}
LocationManager locationManager;
locationManager = (LocationManager) getSystemService(ScoreActivity.this.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(locationManager.NETWORK_PROVIDER);
onLocationChanged(location);
}
#Override
public void onLocationChanged(#NonNull Location location) {
locationDetails=new LatLng(location.getLatitude(),location.getLongitude());
}
In the documentation it has been stated clearly that LocationListener "Used for receiving notifications from FusedLocationProviderApi when the location has changed". On the other hand FusedLocationProviderApi has been marked as deprecated and they recommended to use FusedLocationProviderClient. Then, how to detect when a location has changed when using FusedLocationProviderClient?.
I need that because if I only use the requestLocationUpdate callback, it will update the value regardless of whether the location value changes or not.
I only need changes in location values. That way, it won't waste if I update the location value to the database. In short, updating the location values only that location changes. instead of updating location values based on time span.
The Code:
private void createLocationCallback() {
mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
//every 5 seconds
mLastLocation = locationResult.getLastLocation();
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();//need onLocationChanged
}
};
}
private void startLocationUpdates(){
Log.e(TAG, "startLocationUpdate");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
return;
}
mFusedLocationClient.requestLocationUpdates(mLocationRequest,mLocationCallback, Looper.myLooper());
}
In your LocationRequest, you can use setSmallestDisplacement.
Example
locationRequest.setSmallestDisplacement(10) // 10 meters. location callback only fired when location change more than 10 metter
Another thing is the location accuracy can not 100% so sometime you put don't move the phone but location still change.
When I need to take permission for storage, I simply have a method, like this:
public boolean hasStoragePermission(Activity context, int requestCode){
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&&
ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
return false;
}
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&&
ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},requestCode);
return false;
}
return true;
}
Now I can call this function whenever I need:
if(hasStoragePermission(context, requestCode){
//do the work
}
But in case of location:
public boolean hasPermission(){
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
return true;
}
And when I call it:
public void read(final LocationSetter locationSetter) {
if(!hasPermission()){return;}
flpClient = LocationServices.getFusedLocationProviderClient(this);
flpClient.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
locationSetter.processLocation(location);
}
});
}
It says that Call requires permission. Why is that?
Lint checks are powerful, but they are not magic. This Lint rule is looking for evidence that you have the code to check for runtime permissions, and it does not see it.
It is possible that you will have better luck if you replace the if-negative-then-return approach with an if-positive-do-work approach:
if (hasPermission()) {
// TODO insert your fused location provider work here
}
Or, just suppress the Lint check for this particular method. There should be a quick-fix for that available from Android Studio. In the end, the Lint rule is there to help ensure that you do the right thing, and if you are certain that you are doing the right thing, you do not need that Lint rule in this case.
I have been working on google maps and below is the method I am using to initialize the map. Surprisingly, mapFragment.getMapAsync() method is not getting executed so googleMaps object is still null after calling getMapAsync().
// Initialize the google map
void initMap() {
Log.d(MAPSACTIVITY_TAG, "Initializing google map");
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.maps_fragment);
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap gMap) {
Log.d(MAPSACTIVITY_TAG,"Maps is ready");
googleMap=gMap;
}
});
Log.d(MAPSACTIVITY_TAG,"Value of google maps is "+googleMap);
//This will get device location, set GoogleAPIClient and set mundu marker
if (isLocationPermissionGranted) {
getDeviceLocation();
buildGoogleApiClient();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, "Sorry! App requires location permission", Toast.LENGTH_SHORT).show();
return;
}
googleMap.setMyLocationEnabled(true);
//this will get client's location and set client's marker
geoLocateClient();
} else
Log.d(MAPSACTIVITY_TAG, "Location permission is not given");
}
Here is the Logcat snapshot:
Please notice, Log statement in the getMapAsync is never executed. Can anyone help me with this?
Edit:
Someone marked this question as a duplicate of What is a NullPointerException, and how do I fix it? Please notice this question is about how and when onMapReady() method is called by getMapAync() (its nothing related to the null pointer exception)
You should move code that uses variable googleMap inside onMapReady(...) { ... } method because getMapAsync(...) is asynchronous and onMapReady(...) will be called later in a different thread after Maps has responded.
I am starting to learn about the runtime permissions. I have a map and I made a permission. If user allows fine location - map zooms to his current location, and if he doesn't allow it, the map stays in the place. What I want to do instead of map staying in the place is this: if the user doesn't allow permission for accessing his location, map should zoom in to my custom location (Greenwich).
My maps fragment:
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_LOCATION_REQUEST_CODE);
}
return;
}
mMap.setMyLocationEnabled(true);
LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
// if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION)
// == PackageManager.PERMISSION_GRANTED) {
// mMap.setMyLocationEnabled(true);
// } else {
// // Show rationale and request permission.
// }
//Disable Map Toolbar:
mMap.getUiSettings().setMapToolbarEnabled(false);
// Get the name of the best provider and current location
String provider = null;
if (locationManager != null) {
provider = locationManager.getBestProvider(criteria, true);
}
// Get current location
Location myLocation = null;
if (locationManager != null) {
myLocation = locationManager.getLastKnownLocation(provider);
}
// Set default latitude and longitude to Greenwich
double latitude = 51.4825766;
double longitude = -0.0076589;
// Get latitude and longitude of the current location and a LatLng object
if (myLocation != null) {
latitude = myLocation.getLatitude();
longitude = myLocation.getLongitude();
}
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(latitude, longitude)).zoom(14).build();
mMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
You can zoom to location manually with this code :
CameraUpdate center=CameraUpdateFactory.newLatLng(new LatLng(latitude,
longitude));
CameraUpdate zoom=CameraUpdateFactory.zoomTo(15);
map.moveCamera(center);
map.animateCamera(zoom);
Couldn't find solution so I put the permission inside the parent activity. I think it is a known bug.