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.
Related
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.
I'm developing a simple android location app but I have a little bit trauble.(Also sorry for my bad english.)
I want to get current location with button click, but getLastKnownLocation returns null all of first time.
But also if I first opened google maps and show my current location on map, after that I passed background it then I opened my own app, click the button that works. But I dont want this way, I just want provide location on the my app not with this way.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Object clipboardService = getSystemService(CLIPBOARD_SERVICE);
final ClipboardManager clipboardManager = (ClipboardManager) clipboardService;
tvEnlem = (TextView) findViewById(R.id.textViewEnlem);
tvBoylam = (TextView) findViewById(R.id.textViewBoylam);
retrieveLocationButton = (Button) findViewById(R.id.buttonNeredeyim);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
// 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;
}
retrieveLocationButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showCurrentLocation();
}
});
}
protected void showCurrentLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
// 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;
}
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
String message = String.format(
"Current Location \n Longitude: %1$s \n Latitude: %2$s",
location.getLongitude(), location.getLatitude()
);
Toast.makeText(MainActivity.this, message,
Toast.LENGTH_LONG).show();
this.tvBoylam.setText(String.valueOf(location.getLongitude()));
this.tvEnlem.setText(String.valueOf(location.getLatitude()));
}
else{
Toast.makeText(MainActivity.this,"LOKASYON BİLGİLERİ BOŞ",
Toast.LENGTH_SHORT).show();
}
}
private class MyLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
String message = String.format(
"New Location \n Longitude: %1$s \n Latitude: %2$s",
location.getLongitude(), location.getLatitude()
);
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
}
public void onStatusChanged(String s, int i, Bundle b) {
Toast.makeText(MainActivity.this, "Provider status changed",
Toast.LENGTH_LONG).show();
}
public void onProviderDisabled(String s) {
Toast.makeText(MainActivity.this,
"Provider disabled by the user. GPS turned off",
Toast.LENGTH_LONG).show();
}
public void onProviderEnabled(String s) {
Toast.makeText(MainActivity.this,
"Provider enabled by the user. GPS turned on",
Toast.LENGTH_LONG).show();
}
}
}
How can I get location without null values?
this isn't a bug but simply the Google politics.
The getLastKnowLocation() method return the last location that google service has retrieved.
As Google Documentation says:
The location object may be null in the following situations:
Location is turned off in the device settings. The result could be null even if the last location was previously retrieved because
disabling location also clears the cache.
The device never recorded its location, which could be the case of a new device or a device that has been restored to factory
settings.
Google Play services on the device has restarted, and there is no active Fused Location Provider client that has requested
location after the services restarted.
This is why if you switch from Google Maps to your app, you can get last location.
To get actual position without pass from an app to other, you need to implement a new client and request location updates yourself. For more information, see Receiving Location Updates.
I hope I have clarified your every doubt. Otherwise, do not hesitate to write :)
I am programming an Android App in Java. The activity holds a Google map and what I want is to have a button location at the top, like is shown in the picture:
I want that when I click the location to point to my current Location and for that I am using the class FusedLocationProviderClient.
When I run the program everything goes fine until i follow these steps sequencially:
1- Run app first time and I deny permissions
2- Run app second time. It request again permissions so I answer ok, but the button doesn't appear.
3- I close the app, and because I said yes last time, to the location permission, the button is on the map and is working.
Here is my code:
private void checkPermissions(int fineLocationPermission) {
if (fineLocationPermission != PackageManager.PERMISSION_GRANTED) { //If we don't have any permissions yet
// TODO: Consider calling
//We have to request permissions and in case the user refuse the permission we show an explanation of why he needs the permission
//The following method returns true in case the user reject the permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSION_REQUEST_CODE);
} else
mLocationPermissionGranted=true;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//If the user accepts the dialog box then we get the last location and show button
mLocationPermissionGranted=true;
} else {
mLocationPermissionGranted=false;
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
}
}
public void onLocationChanged(final Location location) {
String msg = "Updated location: " +
Double.toString(location.getLatitude()) + ", " +
Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
final LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
//Show button to locate current position
mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
#Override
public boolean onMyLocationButtonClick() {
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
CameraUpdateFactory.newLatLngZoom(latLng,12);
//mMap.setMaxZoomPreference(12);
return false;
}
});
// Add a marker our current position
LatLng CurrentPosition = new LatLng(location.getLatitude(), location.getLongitude());
mMap.addMarker(new MarkerOptions().position(CurrentPosition).title("Here you are!"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(CurrentPosition));
}
#Override
public void onMapReady(GoogleMap googleMap) {
//Create the map
mMap = googleMap;
//Set the type of the map: HYBRID, NORMAL, SATELLITE or TERRAIN. In our case TERRAIN type
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
//Set the zoom
mMap.setMaxZoomPreference(12);
//Set the markers
MarkerOptions markerOptions= new MarkerOptions();
//Checking permissions with the permissions we have included in the manifiest
checkPermissions(permissionCheckFineLocation);
if (mLocationPermissionGranted) {
try {
mMap.setMyLocationEnabled(true);
//Last location task
Task<Location> locationResult = mFusedLocationClient.getLastLocation();
locationResult.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
//Got last known location. In some rare situations this can be null
if (location != null) {
//Logic to handle location object
onLocationChanged(location);
}
}
});
} catch (SecurityException e) {
Log.e("error", e.getMessage());
}
}
}
I know is a weird question, but I don't know how to express myself.
Any help would be great!
Thank you in advance!
onMapReady isn't called (again) after permission is granted (this happens after onMapReady).
Move the code in onMapReady in the if (mLocationPermissionGranted) clause to a separate method and call it from inside the if as well as from onRequestPermissionsResult if permission was granted.
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;
}
Currently when asking for run time permission when launching my app for the very first time it prompts the user to use their location. And if you click yes it doesn't enable location like it should.
But if I relaunch the app it enables the location. Any suggestions as to where I can get it to have location enabled on first launch ? The first part of the code is called in OnCreate.
if (ContextCompat.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an expanation 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.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_CODE_ASK_PERMISSIONS) {
if (permissions.length == 1 &&
permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else {
// Show rationale and request permission.
}
mMap.setMyLocationEnabled(true);
} else {
//permission denied
}
}
}
public void onMapReady(GoogleMap googleMap) {
int permissionCheck = ContextCompat.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION);
If you are testing on an emulator the permission will only be asked on the first run. How to debug Android 6.0 permissions?
Also if you are not completely uninstalling the app and it is being upgraded from a lower SDK or permissions have been set by the user at runtime and made default, then the runtime permissions will not be asked again.
Try completely uninstalling the app, or checking the default settings and clearing them.
Take a closer look at this line
permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION
permissions is a String array meaning that you should compare using equals()
or compareTo() method.
If this code is in a Fragment, OnRequestPermissionResult() won't be called. So setMyLocationEnabled won't be called until you re open the app.
To fix this change:
ActivityCompat.requestPermissions(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
To:
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
ActivityCompat.requestPermissions is for Activities. When you use a Fragment you should call requestPermissions directly.