I'm trying to learn SmartLocationLibrary for Android to get location and the location I get from it is always null, so I get null object reference errors when I try to do something with it.
I made a Utility class for SmartLocatonLibrary
public class LocationUtil implements OnLocationUpdatedListener, OnActivityUpdatedListener {
private final String TAG = "LocationUtil: ";
private Location location;
private DetectedActivity activity;
private LocationGooglePlayServicesProvider provider;
private Context context;
public LocationUtil(Context context) {
this.context = context;
}
/**
* If lastLocation is not null then the location is set to last location recorded by phone
*/
public void getLastLocation(){
Location lastLocation = SmartLocation.with(context).location().getLastLocation();
if(lastLocation != null){
location = lastLocation;
}
DetectedActivity detectedActivity = SmartLocation.with(context).activity().getLastActivity();
if(detectedActivity != null) activity = detectedActivity;
}
/**
* Basically this starts the location tracking
* If you want one tick of location use .oneFix() on the smartLocation builder
* If you want continous tracking just don't add the .oneFix()
*/
public void startLocation(){
provider = new LocationGooglePlayServicesProvider();
provider.setCheckLocationSettings(true);
SmartLocation smartLocation = new SmartLocation.Builder(context).logging(true).build();
smartLocation.location(provider)
.continuous()
.start(this);
smartLocation.activity()
.start(this);
}
/**
* This stops the tracking
*/
public void stopLocation(){
SmartLocation.with(context).location().stop();
Log.d(TAG, "stopLocation: Location Stopped");
SmartLocation.with(context).activity().stop();
Log.d(TAG, "stopLocation: Activity Recognition Stopped");
}
#Override
public void onActivityUpdated(DetectedActivity detectedActivity) {
this.activity = detectedActivity;
}
#Override
public void onLocationUpdated(Location location) {
this.location = location;
}
//--------SETTERS----------
public void setProvider(LocationGooglePlayServicesProvider provider) {
this.provider = provider;
}
//--------GETTERS----------
public Location getLocation() {
return location;
}
public LocationGooglePlayServicesProvider getProvider() {
return provider;
}
}
And here is the Maps Activity that use it
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private final String TAG = "MAPY";
private int LOCATION_PERMISSION_ID = 1001;
private GoogleMap mMap;
Location location;
LocationUtil locationUtil = new LocationUtil(MapsActivity.this);
Button centerButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
centerButton = findViewById(R.id.centerCameraBtn);
centerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(location != null)
mMap.moveCamera((CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude()))));
}
});
}
#Override
protected void onStop() {
super.onStop();
locationUtil.stopLocation();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
//Check for permissions if they are not granted request them
if (ContextCompat.checkSelfPermission(MapsActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MapsActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_ID);
return;
} else{
locationUtil.startLocation();
}
locationUtil.getLastLocation();
Log.d(TAG, "onMapsReady.lat: " + location.getLatitude() + " onMapsReady.lng: " + location.getLongitude());
location = locationUtil.getLocation();
LatLng currentLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.addMarker(new MarkerOptions().position(currentLocation).title("My current location").snippet("This is a sinppet"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(currentLocation));
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(locationUtil.getProvider() != null){
locationUtil.getProvider().onActivityResult(requestCode, resultCode, data);
}
}
}
I did it like the author of the library showed here but it doesn't work. And the funny thing is it worked yesterday. I'm testing it on my personal phone. The location, mobile data and wifi are turned on and working fine. I got the permissions, i added the permissions to the manifest(both FINE and COARSED) and in my dependencies are
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support:support-media-compat:28.0.0'
implementation 'io.nlopez.smartlocation:library:3.3.3'
implementation 'com.google.android.gms:play-services-maps:16.0.0'
implementation 'com.google.android.gms:play-services-location:16.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
I really don't know whats going on, please help me.
OK so this doesn't work because I want to log the value of the location variable that hasn't been initialised. Debugging it with debugger shows that I'm getting the location. But to be more funny since this is a project just to test the library in the main app the same Utility class won't fetch me a location even if I'm doing everything same as here...
Related
PLZ HELP!
THANK YOU in advance IF YOU Help.
I am using google map API in my android project where I need to locate device current position. I am successfully able to get current device Geo points (Longitude and Latitudes) but I could not able to show my current position in Map. Default map is showing and I am able to get geo points using Toasts.
Here is what I tried: I am just copy and pasting all code. Please focus only on which is important. I was not sure so I pasted all.
For showing geo point into map I tried this 3 lines of code but not sure where to put this this code.
LatLng currentLocation = new LatLng(latitude,longitude);
mMap.addMarker(new MarkerOptions().position(currentLocation).title("Marker in Current Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(currentLocation));
This is Maps_Activity.
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback,
LocationListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private String lang,lat;
Double latitude;
Double longitude;
private Location mylocation;
private GoogleApiClient googleApiClient;
private GoogleMap mMap;
private final static int REQUEST_CHECK_SETTINGS_GPS=0x1;
private final static int REQUEST_ID_MULTIPLE_PERMISSIONS=0x2;
#Override
public void onMapReady(GoogleMap googleMap) {
/*
LatLng currentLocation = new LatLng(latitude,longitude);
mMap.addMarker(new MarkerOptions().position(currentLocation).title("Marker in Current Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(currentLocation));
*/
mMap = googleMap;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpGClient();
}
private synchronized void setUpGClient() {
googleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, 0, this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
mylocation = location;
if (mylocation != null) {
latitude=mylocation.getLatitude();
longitude=mylocation.getLongitude();
String _lang = longitude + "";
String _lat = latitude + "";
Toast.makeText(this, "Longitude: " + _lang + "\nLatitude: " + _lat, Toast.LENGTH_LONG).show();
//Or Do whatever you want with your location
}
}
#Override
public void onConnected(Bundle bundle) {
checkPermissions();
}
#Override
public void onConnectionSuspended(int i) {
//Do whatever you need
//You can display a message here
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
//You can display a message here
}
private void getMyLocation(){
if(googleApiClient!=null) {
if (googleApiClient.isConnected()) {
int permissionLocation = ContextCompat.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
mylocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
LocationRequest locationRequest = new LocationRequest();
locationRequest.setInterval(30*1000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
LocationServices.FusedLocationApi
.requestLocationUpdates(googleApiClient, locationRequest, this);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi
.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied.
// You can initialize location requests here.
int permissionLocation = ContextCompat
.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
mylocation = LocationServices.FusedLocationApi
.getLastLocation(googleApiClient);
// mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
//mMap.animateCamera(CameraUpdateFactory.zoomTo(15.5f));
}
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied.
// But could be fixed by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
// Ask to turn on GPS automatically
status.startResolutionForResult(MapsActivity.this,
REQUEST_CHECK_SETTINGS_GPS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied.
// However, we have no way
// to fix the
// settings so we won't show the dialog.
// finish();
break;
}
}
});
}
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CHECK_SETTINGS_GPS:
switch (resultCode) {
case Activity.RESULT_OK:
getMyLocation();
break;
case Activity.RESULT_CANCELED:
finish();
break;
}
break;
}
}
private void checkPermissions(){
int permissionLocation = ContextCompat.checkSelfPermission(MapsActivity.this,
android.Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (permissionLocation != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this,
listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
}
}else{
getMyLocation();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
int permissionLocation = ContextCompat.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
getMyLocation();
}
}
}
Try this code in onLocationChanged() Method:
if(REQUEST_CHECK_SETTINGS_GPS!=0) {
LatLng latLng = new LatLng(mylocation.getLatitude(), mylocation.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16.0f));
mMap.addMarker(new MarkerOptions().position(new LatLng(mylocation.getLatitude(), mylocation.getLongitude())).title("Current Location"));
}
Here mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16.0f)); you can pass any floating value which refers to zoom level you want . you can simply just try different values and see what is best for you.
Try this and let me know if it works.
You can use the My Location Layer of Maps SDK for Android to directly get your device's current location as well as displaying it in your map. The full sample code can be found here.
Also if you already have your latlng coordinates and you just need to display your current location on a map using a marker, you can add the following codes inside your onMapReady() method:
LatLng currentLocation = new LatLng(latitude,longitude);
float zoom = 17.0f //Set a zoom level of your preference
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLocation, zoom));
mMap.addMarker(new MarkerOptions().position(currentLocation).title("Current Location").snippet("My Current Location"));
Note: Instead of using CameraUpdateFactory.newLatLng(), use CameraUpdateFactory.newLatLngZoom(). THis works for me every time. Just provide a float value for your zoom level. Also, make sure that the value of LatLng currentLocation is not null.
Hope this helps!
I am trying to add a marker on my Google maps by long-pressing on the location and displaying the name of the location, however, whenever I long-press the marker appears for a split second and then goes away (disappears).
I understand after the long-press the marker is supposed to stay and then show the title as well, but that is not working.
Please do let me know if anyone is facing any such issue and can help me with it.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMapLongClickListener {
private GoogleMap mMap;
LocationManager locationManager;
LocationListener locationListener;
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
centerMapOnLocation(lastKnownLocation, "Your Location");
}
}
}
public void centerMapOnLocation(Location location, String title) {
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.clear();
if (title != "Your Location"){
mMap.addMarker(new MarkerOptions().position(userLocation).title(title));
}
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 10));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapLongClickListener(this);
Intent intent = getIntent();
if (intent.getIntExtra("placeNumber", 0) == 0) {
//zoom in on the user's location
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
centerMapOnLocation(location, "Your Location");
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
if (Build.VERSION.SDK_INT < 23) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#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 Activity#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
} else {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
centerMapOnLocation(lastKnownLocation, "Your Location");
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}
}
}
}
#Override
public void onMapLongClick(LatLng latLng) {
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
String address ="";
try {
List <Address> listAddresses= geocoder.getFromLocation(latLng.latitude,latLng.longitude,1);
if (listAddresses!=null&& listAddresses.size()>0){
if (listAddresses.get(0).getThoroughfare()!=null){
if (listAddresses.get(0).getSubThoroughfare()!=null){
address+=listAddresses.get(0).getSubThoroughfare()+" ";
}
address+= listAddresses.get(0).getThoroughfare();
}
}
} catch (IOException e) {
e.printStackTrace();
}
if (address == ""){
SimpleDateFormat sdf = new SimpleDateFormat("mm:HH yyyyMMdd", Locale.getDefault());
address = sdf.format(new Date());
}
mMap.addMarker(new MarkerOptions().position(latLng).title(address).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));
}
}
You are clearing your map every time your location changes here:
#Override
public void onLocationChanged(Location location) {
centerMapOnLocation(location, "Your Location");
}
That's why your marker disappears right after you add it to the map. If you remove or comment out this line within your centerMapOnLocation method:
mMap.clear();
Then the markers no longer disappear.
Hope this helps!
I'm a student currently learning and try to play around with google map api. Right now, I'm facing a problem with the getting the location lat, long. Yesterday, I can use it just fine, but suddenly I cannot use it anymore today. The code is kinda long, because I wanted to show that the app asked for permission for the location to be turn on before using the apps but I don't think I get it correctly. I don't think the app starts like how I wanted it to start.
The process should be, from previous activity intent to this MapsActivity will prompt the request permission to open location, and once the location is on, the google map marker will update to the current location.
Right now, the apps just keeps on crashing.
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
FusedLocationProviderClient mFusedLocationClient;
LocationRequest mLocationRequest;
LocationCallback mLocationCallback;
double mLocationLat, mLocationLong;
LocationSettingsRequest.Builder mLocationSettingsBuilder;
SettingsClient client;
Task<LocationSettingsResponse> task;
private static final int REQUEST_CHECK_SETTINGS = 0x1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//toolbar.setTitle("AskForMech : Maps");
//toolbar.setLogo(R.drawable.ic_launcher);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MapsActivity.this);
mLocationCallback = new LocationCallback(){
#Override
public void onLocationResult(LocationResult locationResult) {
if(locationResult==null){
return;
} else {
mLocationLat = locationResult.getLastLocation().getLatitude();
mLocationLong = locationResult.getLastLocation().getLongitude();
}
}
};
setLocationRequestSettings();
}
public void getLocation(){ //error is here
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
mLocationLat = location.getLatitude();
mLocationLong = location.getLongitude();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
getLocation(); //error is here
LatLng pos = new LatLng(mLocationLat, mLocationLong);
mMap.addMarker(new MarkerOptions().position(pos).title("You!"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(pos));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(pos, 18.00f));
}
#Override
protected void onResume() {
super.onResume();
//startLocationUpdate();
requestLocationUpdate();
}
#Override
protected void onPause() {
super.onPause();
if(mFusedLocationClient != null){
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
Toast.makeText(MapsActivity.this, "Listener is removed.", Toast.LENGTH_SHORT).show();
}
}
private void requestLocationUpdate(){
mLocationSettingsBuilder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
client = LocationServices.getSettingsClient(MapsActivity.this);
task = client.checkLocationSettings(mLocationSettingsBuilder.build());
task.addOnSuccessListener(MapsActivity.this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
startLocationUpdate();
}
});
task.addOnFailureListener(MapsActivity.this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if(e instanceof ResolvableApiException){
try{
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MapsActivity.this, REQUEST_CHECK_SETTINGS);
}catch(IntentSender.SendIntentException sendEx) {
}
}
}
});
}
private void setLocationRequestSettings(){
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(3000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private void startLocationUpdate(){
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
showExplanation();
} else {
ActivityCompat.requestPermissions(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
0);
}
} else {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, null);
Toast.makeText(MapsActivity.this, "Location permission was granted!", Toast.LENGTH_SHORT).show();
}
}
private void showExplanation(){
AlertDialog.Builder builder = new AlertDialog.Builder(MapsActivity.this);
builder.setTitle("Requires Location Permission.");
builder.setMessage("This app needs location permission to get the location information.");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCompat.requestPermissions(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
0);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MapsActivity.this, "Sorry, this function cannot be used until permission is granted.",Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
}
you should use the callback method onLocationChanged() instead of getLastKnownLocation (). Indeed, getLastKnownLocation() can return null (see here)
I prefer to use onLocationChanged() that is called once a location change is detected. It turns out that it works great for me.
If you have any trouble to implement a LocationListener, take a look at this post : https://stackoverflow.com/a/42218626/3780625
Best
I have an app that needs the location of the user, and I am new in implementing location service of Google.
I made a separate java class to handle things related to getting location, and then using the location information in a activity just to show the location(so far), but I get the default value of 0 for latitude and longitude in my activity.
Here's the java class implementing the location related stuff, following google guideline:
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
public class CommentLocation implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private double mLatitude;
private double mLongitude;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
public CommentLocation(Context context){
buildGoogleApiClient(context);
}
public double getCommentLongitude() {
return mLongitude;
}
public double getCommentLatitude() {
return mLatitude;
}
protected synchronized void buildGoogleApiClient(Context context) {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onConnected(Bundle connectionHint) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
mLatitude = mLastLocation.getLatitude();
mLongitude = mLastLocation.getLongitude();
}
else{
Log.v(CommentLocation.class.getName(), "LOCATION WAS NOT RECEIVED");
}
Log.v(CommentLocation.class.getName(), "CONNECTION TO GET LOCATION IS SUCCESSFUL");
}
#Override
public void onConnectionSuspended(int i) {
//TODO
Log.v(CommentLocation.class.getName(), "CONNECTION TO GET LOCATION IS SUSPENDED");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
//TODO
Log.v(CommentLocation.class.getName(), "CONNECTION TO GET LOCATION IS FAILED");
}
}
And here is the caller of this location class (the fragment PostCommentFragment)
public class PostCommentFragment extends Fragment {
private TextView mLatitudeText;
private TextView mLongtitudeText;
private CommentDatabase database;
private CommentLocation location;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
database = new CommentDatabase(getActivity());
location = new CommentLocation(getActivity());
setHasOptionsMenu(true);
}
#TargetApi(11) //for setDisplayHomeAsUpEnabled function
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_post_comment, container, false);
//to enable the app icon to work as a button and get the caret to appear in fragment's view
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
if(NavUtils.getParentActivityName(getActivity()) != null) {
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
mLatitudeText = (TextView) v.findViewById(R.id.latitude_text);
mLongtitudeText = (TextView) v.findViewById(R.id.longitude_text);
mLatitudeText.setText(String.valueOf(location.getCommentLatitude()));
mLongtitudeText.setText(String.valueOf(location.getCommentLongitude()));
return v;
}
What am I doing wrong here?
I also added this line compile 'com.google.android.gms:play-services:7.8.0'
to build.gradle(Module:app)->under dependencies, and asked for permission in Manifest. Thanks!
Issue 1:
You're not calling connect() on mGoogleApiClient.
You need to call connect in order for onConnected() to be invoked:
public CommentLocation(Context context){
buildGoogleApiClient(context);
mGoogleApiClient.connect(); //added
}
Issue 2:
It looks like you're only using getLastLocation(). This may work for your needs, but if you need a location, this method is not guaranteed to give one. The getLastLocation() method can and will return null. The main problem is that it doesn't prompt a request to the OS for a new location lock, instead it just checks if there was a last known location from some other app's location request. If no other app had recently made a location request, then you get a null location returned to you.
The only way to guarantee that you actually get a location is to request one, and this is done with a call to requestLocationUpdates().
Issue 3:
Given that it takes time to connect to the Google Api Client, the timing may be off, and even if you get a location from getLastLocation(), you may have already requested it from your Fragment.
To get around this issue, you could use a BroadcastReceiver to send the location from the CommentLocation class to the Fragment.
Note that in general keeping the location functionality encapsulated is a better approach, but it's more work to implement. You might want to go with a more simple design, where the location functionality is within the Activity that is associated with this Fragment. Then you could just call into the Fragment when a location is available.
Sample Activity code with a location listener:
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildGoogleApiClient();
mGoogleApiClient.connect();
}
#Override
protected void onPause(){
super.onPause();
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();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10);
mLocationRequest.setFastestInterval(10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
//mLocationRequest.setSmallestDisplacement(0.1F);
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) {
Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude());
Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show();
}
}
How do I get the current Latitude and Longitude of the mobile device in android using location tools?
Use the LocationManager.
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double longitude = location.getLongitude();
double latitude = location.getLatitude();
The call to getLastKnownLocation() doesn't block - which means it will return null if no position is currently available - so you probably want to have a look at passing a LocationListener to the requestLocationUpdates() method instead, which will give you asynchronous updates of your location.
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
longitude = location.getLongitude();
latitude = location.getLatitude();
}
}
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener);
You'll need to give your application the ACCESS_FINE_LOCATION permission if you want to use GPS.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
You may also want to add the ACCESS_COARSE_LOCATION permission for when GPS isn't available and select your location provider with the getBestProvider() method.
Here is the class LocationFinder to find the GPS location. This class will call MyLocation, which will do the business.
LocationFinder
public class LocationFinder extends Activity {
int increment = 4;
MyLocation myLocation = new MyLocation();
// private ProgressDialog dialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intermediat);
myLocation.getLocation(getApplicationContext(), locationResult);
boolean r = myLocation.getLocation(getApplicationContext(),
locationResult);
startActivity(new Intent(LocationFinder.this,
// Nearbyhotelfinder.class));
GPSMyListView.class));
finish();
}
public LocationResult locationResult = new LocationResult() {
#Override
public void gotLocation(Location location) {
// TODO Auto-generated method stub
double Longitude = location.getLongitude();
double Latitude = location.getLatitude();
Toast.makeText(getApplicationContext(), "Got Location",
Toast.LENGTH_LONG).show();
try {
SharedPreferences locationpref = getApplication()
.getSharedPreferences("location", MODE_WORLD_READABLE);
SharedPreferences.Editor prefsEditor = locationpref.edit();
prefsEditor.putString("Longitude", Longitude + "");
prefsEditor.putString("Latitude", Latitude + "");
prefsEditor.commit();
System.out.println("SHARE PREFERENCE ME PUT KAR DIYA.");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
// handler for the background updating
}
MyLocation
public class MyLocation {
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled=false;
boolean network_enabled=false;
public boolean getLocation(Context context, LocationResult result)
{
//I use LocationResult callback class to pass location value from MyLocation to user code.
locationResult=result;
if(lm==null)
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//exceptions will be thrown if provider is not permitted.
try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}
//Toast.makeText(context, gps_enabled+" "+network_enabled, Toast.LENGTH_LONG).show();
//don't start listeners if no provider is enabled
if(!gps_enabled && !network_enabled)
return false;
if(gps_enabled)
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
if(network_enabled)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
timer1=new Timer();
timer1.schedule(new GetLastLocation(), 10000);
// Toast.makeText(context, " Yaha Tak AAya", Toast.LENGTH_LONG).show();
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
#Override
public void run() {
//Context context = getClass().getgetApplicationContext();
Location net_loc=null, gps_loc=null;
if(gps_enabled)
gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(network_enabled)
net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//if there are both values use the latest one
if(gps_loc!=null && net_loc!=null){
if(gps_loc.getTime()>net_loc.getTime())
locationResult.gotLocation(gps_loc);
else
locationResult.gotLocation(net_loc);
return;
}
if(gps_loc!=null){
locationResult.gotLocation(gps_loc);
return;
}
if(net_loc!=null){
locationResult.gotLocation(net_loc);
return;
}
locationResult.gotLocation(null);
}
}
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
}
With google things changes very often: non of the previous answers worked for me.
based on this google training here is how you do it using
fused location provider
this requires Set Up Google Play Services
Activity class
public class GPSTrackerActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
Location mLastLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onConnected(Bundle bundle) {
try {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
Intent intent = new Intent();
intent.putExtra("Longitude", mLastLocation.getLongitude());
intent.putExtra("Latitude", mLastLocation.getLatitude());
setResult(1,intent);
finish();
}
} catch (SecurityException e) {
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
usage
in you activity
Intent intent = new Intent(context, GPSTrackerActivity.class);
startActivityForResult(intent,1);
And this method
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1){
Bundle extras = data.getExtras();
Double longitude = extras.getDouble("Longitude");
Double latitude = extras.getDouble("Latitude");
}
}
you can got Current latlng using this
`
public class MainActivity extends ActionBarActivity {
private LocationManager locationManager;
private String provider;
private MyLocationListener mylistener;
private Criteria criteria;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the location provider
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE); //default
// user defines the criteria
criteria.setCostAllowed(false);
// get the best provider depending on the criteria
provider = locationManager.getBestProvider(criteria, false);
// the last known location of this provider
Location location = locationManager.getLastKnownLocation(provider);
mylistener = new MyLocationListener();
if (location != null) {
mylistener.onLocationChanged(location);
} else {
// leads to the settings because there is no last known location
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
// location updates: at least 1 meter and 200millsecs change
locationManager.requestLocationUpdates(provider, 200, 1, mylistener);
String a=""+location.getLatitude();
Toast.makeText(getApplicationContext(), a, 222).show();
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
// Initialize the location fields
Toast.makeText(MainActivity.this, ""+location.getLatitude()+location.getLongitude(),
Toast.LENGTH_SHORT).show()
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Toast.makeText(MainActivity.this, provider + "'s status changed to "+status +"!",
Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(MainActivity.this, "Provider " + provider + " enabled!",
Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(MainActivity.this, "Provider " + provider + " disabled!",
Toast.LENGTH_SHORT).show();
}
}
`
Above solutions is also correct, but some time if location is null then it crash the app or not working properly. The best way to get Latitude and Longitude of android is:
Geocoder geocoder;
String bestProvider;
List<Address> user = null;
double lat;
double lng;
LocationManager lm = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
bestProvider = lm.getBestProvider(criteria, false);
Location location = lm.getLastKnownLocation(bestProvider);
if (location == null){
Toast.makeText(activity,"Location Not found",Toast.LENGTH_LONG).show();
}else{
geocoder = new Geocoder(activity);
try {
user = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
lat=(double)user.get(0).getLatitude();
lng=(double)user.get(0).getLongitude();
System.out.println(" DDD lat: " +lat+", longitude: "+lng);
}catch (Exception e) {
e.printStackTrace();
}
}
Best way is
Add permission manifest file
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
Then you can get GPS location or if GPS location is not available then this function return NETWORK location
public static Location getLocationWithCheckNetworkAndGPS(Context mContext) {
LocationManager lm = (LocationManager)
mContext.getSystemService(Context.LOCATION_SERVICE);
assert lm != null;
isGpsEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkLocationEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
Location networkLoacation = null, gpsLocation = null, finalLoc = null;
if (isGpsEnabled)
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return null;
}gpsLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (isNetworkLocationEnabled)
networkLoacation = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (gpsLocation != null && networkLoacation != null) {
//smaller the number more accurate result will
if (gpsLocation.getAccuracy() > networkLoacation.getAccuracy())
return finalLoc = networkLoacation;
else
return finalLoc = gpsLocation;
} else {
if (gpsLocation != null) {
return finalLoc = gpsLocation;
} else if (networkLoacation != null) {
return finalLoc = networkLoacation;
}
}
return finalLoc;
}
You can use FusedLocationProvider
For using Fused Location Provider in your project you will have to add the google play services location dependency in our app level build.gradle file
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
...
...
...
implementation 'com.google.android.gms:play-services-location:17.0.0'
}
Permissions in Manifest
Apps that use location services must request location permissions. Android offers two location permissions: ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
As you may know that from Android 6.0 (Marshmallow) you must request permissions for important access in the runtime. Cause it’s a security issue where while installing an application, user may not clearly understand about an important permission of their device.
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_ID
)
Then you can use the FusedLocationProvider Client to get the updated location in your desired place.
mFusedLocationClient.lastLocation.addOnCompleteListener(this) { task ->
var location: Location? = task.result
if (location == null) {
requestNewLocationData()
} else {
findViewById<TextView>(R.id.latTextView).text = location.latitude.toString()
findViewById<TextView>(R.id.lonTextView).text = location.longitude.toString()
}
}
You can also check certain configuration like if the device has location settings on or not. You can also check the article on Detect Current Latitude & Longitude using Kotlin in Android for more functionality.
If there is no cache location then it will catch the current location using:
private fun requestNewLocationData() {
var mLocationRequest = LocationRequest()
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
mLocationRequest.interval = 0
mLocationRequest.fastestInterval = 0
mLocationRequest.numUpdates = 1
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
mFusedLocationClient!!.requestLocationUpdates(
mLocationRequest, mLocationCallback,
Looper.myLooper()
)
}
Plug and play location-manager that can be used both in XML-based projects and Jetpack Compose projects (personally using it in JetpackCompose)
class LocationManager(context: Context): LocationCallback() {
val context = context
var publicCompletion: ((Double, Double) -> Unit)? = null
var fusedLocationProviderClient = FusedLocationProviderClient(
context
)
fun requestLocationPermission() {
val activity = context as Activity?
ActivityCompat.requestPermissions(
activity!!,
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION
),
101
)
}
fun checkIfLocationPermissionIsGranted(): Boolean {
return (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
)
}
fun getLatitudeLongitude(completion: (Double, Double) -> Unit) {
publicCompletion = { latitude, longitude ->
completion(latitude, longitude)
}
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
val activity = context as Activity?
fusedLocationProviderClient.lastLocation.addOnCompleteListener(activity!!) { task ->
var location: Location? = task.result
if (location != null) {
publicCompletion?.let { it(location!!.latitude, location!!.longitude) }
} else {
requestLocationUpdates()
}
}
}
}
fun requestLocationUpdates() {
var request = LocationRequest()
request.priority = com.google.android.gms.location.LocationRequest.PRIORITY_HIGH_ACCURACY
request.fastestInterval = 0
request.numUpdates = 1
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
fusedLocationProviderClient.requestLocationUpdates(
request, this, Looper.myLooper()
)
}
}
override fun onLocationResult(p0: LocationResult?) {
super.onLocationResult(p0)
publicCompletion?.let { it(p0!!.lastLocation!!.latitude, p0!!.lastLocation!!.longitude) }
}
override fun onLocationAvailability(p0: LocationAvailability?) {
super.onLocationAvailability(p0)
}
}
Just follow Google recommendation and prepared codes in kotlin: (Supports also Android 11 and 12):
https://github.com/googlecodelabs/while-in-use-location
and its step by step explanation:
https://codelabs.developers.google.com/codelabs/while-in-use-location