Greetings of the day. I'm working on app in which i need to show a map.
I want a map to be shown by default at my current location but i'm not able to do so. I've tried several ways to get Current Location (LatLng).
I followed this link too, the link works fine on emulator when i send LatLng from Android Device Monitor but fails on real device.
and wrote a simple piece of code given below
Location myLoc=mMap.getMyLocation();
double cLat=myLoc.getLatitude();
double cLng=myLoc.getLongitude();
showMap(cLat,cLng);
the above code returns NULL. Got stucked . Please help
You should handle the case where the Location is null, and fallback to a sensible default, like centering the map on a major city. Google's documentation states that the Location can be null in rare cases. In practice I have found this happens most often when the device has been indoors for a long time, or has had location services disabled.
public class SplashScreen extends Activity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
// LogCat tag
private static final String TAG = MainActivity.class.getSimpleName();
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
CheckGPS();
ImageView textView = (ImageView) findViewById(R.id.center);
Animation logoMoveAnimation = AnimationUtils.loadAnimation(this, R.anim.splash);
textView.startAnimation(logoMoveAnimation);
}
private void setUpLocation() {
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
}
}
/**
* Method to display the location on UI
*/
private void displayLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
getCities(latitude, longitude);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(SplashScreen.this, MainActivity.class));
finish();
}
}, 4000);
} else {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(SplashScreen.this, MainActivity.class));
finish();
}
}, 4000);
}
}
private void getCities(double lat, double lng) {
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(lat, lng, 1);
String cityName = addresses.get(0).getLocality();
//String locality = addresses.get(0).getSubLocality();
API.OnCityID(SplashScreen.this, cityName);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
finish();
}
return false;
}
return true;
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
// Once connected with google api, get the location
displayLocation();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
private void CheckGPS() {
// Get Location Manager and check for GPS & Network location services
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
!lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
// Build the alert dialog
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Location Services Not Active");
builder.setMessage("Please enable Location Services and GPS");
builder.setPositiveButton("Setting", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
// Show location settings when the user acknowledges the alert dialog
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
finish();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
// Show location settings when the user acknowledges the alert dialog
dialogInterface.dismiss();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(SplashScreen.this, MainActivity.class));
finish();
}
}, 1500);
}
});
Dialog alertDialog = builder.create();
alertDialog.setCanceledOnTouchOutside(false);
alertDialog.show();
} else {
setUpLocation();
}
}
}
Related
I'm building a friend tracking android app. While my friend activated the app and goes away along with his GPS and cellular data on, I need to track him on my device. That's the concept.
I've implemented LocationListener class and now I can get the last updated location either from Gps or Network but is not updated unless I launch Google Maps and return to my application. After googling, I learned that location cache is updated only by GMaps.!
Is there an alternate way to continuously update location?
What if when I need to get continues location after the device locked without making use of Wakelock?
This is my location listener class:
package com.amazinginside;
/** AMAZING LOCATION SUPPORT CLASS, Devoloped By SANGEETH NANDAKUMAR */
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
public class AmazingLocation extends Service implements LocationListener
{
private final Context mContext;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
double latitude=0.0;
double longitude=0.0;
//MINIMUM DISTANCE FOR UPDATE (meters)
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 Meters
//MINIMUM TIME BETWEEN UPDATES
private static final long MIN_TIME_BW_UPDATES = 1000 * 0; // 0 Seconds
//LOCATION MANAGER
protected LocationManager locationManager;
//CONSTRUCTOR
public AmazingLocation(Context context)
{
this.mContext = context;
getLocation();
}
//LOCATION PROVISION
public Location getLocation()
{
try
{
//GET LOCATION MANAGER
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
//CHECK GPS STATE
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
//CHECK NETWORK STATE
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled)
{
//NO LOCATION PROVIDERS
}
else
{
this.canGetLocation = true;
/** GET LOCATION FROM NETWORK */
//FIRST GET LOCATION FROM NETWORK
if (isNetworkEnabled)
{
//REQUEST LOCATION
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
//START WITH LAST KNOWN LOCATION
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//EXTRACT LOCATION
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
/** GET LOCATION FROM GPS SENSOR */
//THEN GET LOCATION FROM GPS
if (isGPSEnabled)
{
if (location == null)
{
//REQUEST GPS LOCATION
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
//EXTRACT LAST KNOWN LOCATION
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//RETURN LOCATION
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return location;
}
//STOP GPS SENSOR
public void stopUsingGPS()
{
if(locationManager != null)
{
locationManager.removeUpdates(AmazingLocation.this);
}
}
//EXTRACT LATTITUDE
public double getLatitude()
{
if(location != null)
{
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
//EXTACT LONGITUDE
public double getLongitude()
{
if(location != null)
{
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
//CAN I GET THE LOCATION.?
public AmazingStatus canGetLocation()
{
AmazingStatus status=new AmazingStatus();
if(this.canGetLocation)
{
status.setStatus(true);
status.setErrorcode(0);
status.setErrormsg("Task completed");
}
else
{
status.setStatus(false);
status.setErrorcode(145);
status.setErrormsg("Please turn on GPS access manually");
}
return status;
}
//SHOW LOCATION SETTINGS
public AmazingStatus showSettingsAlert()
{
final AmazingStatus status=new AmazingStatus();
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("REQUIRES LOCATION ACCESS");
alertDialog.setMessage("Please allow GPS access to this app");
//POSSITIVE REPLY
alertDialog.setPositiveButton("Allow", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int which)
{
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
status.setStatus(true);
status.setErrorcode(0);
status.setErrormsg("Task completed");
}
});
//NEGATIVE REPLY
alertDialog.setNegativeButton("Deny", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
status.setStatus(false);
status.setErrorcode(408);
status.setErrormsg("User denied permission");
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
return status;
}
//UNUSED OVERRIDE METHORDS...
#Override
public void onLocationChanged(Location location)
{
getLocation();
}
#Override
public void onProviderDisabled(String provider)
{
}
#Override
public void onProviderEnabled(String provider)
{
getLocation();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
getLocation();
}
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
}
This my onCreate() method:
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//CREATE A BUTTON HANDLER
Button start_btn=(Button)findViewById(R.id.start_location_streaming);
//ON BUTTON CLICK EVENT
start_btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//REPEAT A METHORD AT SPECIFIC INTERVALS
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask()
{
#Override
public void run()
{
TimerMethod();
}
}, 0, 8000);
}
}); }
These are other methods:
private void TimerMethod()
{
//START METHORD
this.runOnUiThread(Timer_Tick);
}
//LOCATION REPORTING METHORD
private Runnable Timer_Tick = new Runnable()
{
public void run()
{
Toast.makeText(MainActivity.this, "Current latitude : "+Double.toString(getLocation().latitude), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, "Current longitude : "+Double.toString(getLocation().longitude), Toast.LENGTH_SHORT).show();
}
};
private LatLng getLocation()
{
//CREATE A LOCATION CLASS INSTANCE
AmazingLocation gps = new AmazingLocation(this);
//RETRIVE LOCATION
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
//RETURN LOCATION
LatLng loc=new LatLng(latitude,longitude);
return loc;
}
Now the problem is, the toast just shows previously known the location and not updating unless I opened Google Maps and returned.
Any help will be great for me.
Use Fused location provider in Android set your interval in that:
For an example create your activity like this:
public class LocationActivity extends Activity implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationActivity";
private static final long INTERVAL = 1000 * 10;
private static final long FASTEST_INTERVAL = 1000 * 5;
Button btnFusedLocation;
TextView tvLocation;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
String mLastUpdateTime;
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate ...............................");
//show error dialog if GoolglePlayServices not available
if (!isGooglePlayServicesAvailable()) {
finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
setContentView(R.layout.activity_main);
tvLocation = (TextView) findViewById(R.id.tvLocation);
btnFusedLocation = (Button) findViewById(R.id.btnShowLocation);
btnFusedLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
updateUI();
}
});
}
#Override
public void onStart() {
super.onStart();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
#Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop fired ..............");
mGoogleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
startLocationUpdates();
}
protected void startLocationUpdates() {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Connection failed: " + connectionResult.toString());
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
private void updateUI() {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
tvLocation.setText("At Time: " + mLastUpdateTime + "\n" +
"Latitude: " + lat + "\n" +
"Longitude: " + lng + "\n" +
"Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
"Provider: " + mCurrentLocation.getProvider());
} else {
Log.d(TAG, "location is null ...............");
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}
Google play services required:
To get continiuos location update, you can refer to the above provided answers .
But You can also make use of LocationServices which is faster than other approaches and much easy and efficient to get location.
This approach is quit long but kindly follow all the provided steps
So let me provide a brief working :
Add these two dependencies in your gradle app file
implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.android.gms:play-services-location:17.0.0'
Add these permissions in the manifest file outside applicationtag
Declare variable outside onCreate
private FusedLocationProviderClient fusedLocationClient;
private LocationRequest mLocationRequest;
private LocationCallback mlocationCallback;
private LocationSettingsRequest.Builder builder;
private static final int REQUEST_CHECK_SETTINGS = 102;
Now inside onCreate :
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();
mlocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
// Update UI with location data
// ...
Log.e("CONTINIOUSLOC: ", location.toString());
}
};
};
mLocationRequest = createLocationRequest();
builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
checkLocationSetting(builder);
No define fetchLastLocation method
private void fetchLastLocation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
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.
// Toast.makeText(MainActivity.this, "Permission not granted, Kindly allow permission", Toast.LENGTH_LONG).show();
showPermissionAlert();
return;
}
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener() {
#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
Log.e("LAST LOCATION: ", location.toString()); // You will get your last location here
}
}
});
}
Now define other two method for permission request
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 123: {
// If request is cancelled, the result arrays are empty.
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// permission was denied, show alert to explain permission
showPermissionAlert();
}else{
//permission is granted now start a background service
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fetchLastLocation();
}
}
}
}
}
private void showPermissionAlert(){
if (ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainHomeActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 123);
}
}
now define createLocationRequest method and checkLocationSetting method :
protected LocationRequest createLocationRequest() {
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(30000);
mLocationRequest.setFastestInterval(10000);
mLocationRequest.setSmallestDisplacement(30);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
return mLocationRequest;
}
private void checkLocationSetting(LocationSettingsRequest.Builder builder) {
SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
startLocationUpdates();
return;
}
});
task.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull final Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
AlertDialog.Builder builder1 = new AlertDialog.Builder(mContext);
builder1.setTitle("Continious Location Request");
builder1.setMessage("This request is essential to get location update continiously");
builder1.create();
builder1.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ResolvableApiException resolvable = (ResolvableApiException) e;
try {
resolvable.startResolutionForResult(MainHomeActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e1) {
e1.printStackTrace();
}
}
});
builder1.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(mContext, "Location update permission not granted", Toast.LENGTH_LONG).show();
}
});
builder1.show();
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if (requestCode == REQUEST_CHECK_SETTINGS) {
if (resultCode == RESULT_OK) {
// All location settings are satisfied. The client can initialize
// location requests here.
startLocationUpdates();
}
else {
checkLocationSetting(builder);
}
}
}
now atlast define startLocationUpdates and stopLocationUpdates method :
public void startLocationUpdates() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
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;
}
}
fusedLocationClient.requestLocationUpdates(mLocationRequest,
mlocationCallback,
null /* Looper */);
}
private void stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(mlocationCallback);
}
Note : Replace context with your class context and call stopLocationUpdates() inside onDestroy method of your class
Note : For any futher information or doubt you can refer to :
https://developer.android.com/training/location/retrieve-current
https://developer.android.com/training/location/change-location-settings
https://developer.android.com/training/location/receive-location-updates
You will get your location in Logcat.
Hope this will hope you or somebody else !
I believe rather than reinventing the wheel, you can use one of the third party libraries that are easy to implement and in this case, battery efficient. One of the library I found is SmartLocation. You can add the following dependency in your build.gradle (app) to start using the library.
compile 'io.nlopez.smartlocation:library:3.2.9'
After adding the dependency, you should rebuild the project to get the references.
As an example you can try the following code in your Activity.
Button start_btn=(Button)findViewById(R.id.start_location_streaming);
Context context = start_btn.getContext();
Handler handler = new Handler();
start_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SmartLocation.with(context).location().start(locationListener);
}
});
OnLocationUpdatedListener locationListener = new OnLocationUpdatedListener({
#Override
public void onLocationUpdated(Location location) {
double lat = location.getLatitude();
double lng = location.getLongitude();
handler.postDelayed(locationRunnable,8000);
}
});
Runnable locationRunnable = new Runnable({
#Override
public void run() {
SmartLocation.with(context).location().start(locationListener);
}
});
You can stop location tracking in onStop() method
#Override
public void onStop() {
SmartLocation.with(context).location().stop();
super.onStop();
}
SmartLocation library will give you more than what is expected, just try that once.
Note: Make sure your application does have ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION (both) to have accurate results. Don't forget to ask for permissions at runtime for Android 6.0 and above.
You should use android services, rather than the app itself. This way you will achieve to run code continuously in the background and you will receive the location even if the app closes.
https://www.tutorialspoint.com/android/android_services.htm
I'm developing an Android app, and I need to get latitude and longitude of the user.
I googled and found that Google API is the best for this, and I found a tutorial on this link: http://www.androidhive.info/2015/02/android-location-api-using-google-play-services/
How I don't need location updates (just click in a button, and get the location), I just copied this piece of code from tutorial:
public class MainActivity1 extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener {
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// UI elements
private TextView lblLocation;
private Button btnShowLocation, btnStartLocationUpdates;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lblLocation = (TextView) findViewById(R.id.lblLocation);
btnShowLocation = (Button) findViewById(R.id.btnShowLocation);
btnStartLocationUpdates = (Button) findViewById(R.id.btnLocationUpdates);
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
}
// Show location button click listener
btnShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayLocation();
}
});
}
/**
* Method to display the location on UI
* */
private void displayLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
lblLocation.setText(latitude + ", " + longitude);
} else {
lblLocation
.setText("(Couldn't get the location. Make sure location is enabled on the device)");
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
* */
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
finish();
}
return false;
}
return true;
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
// Once connected with google api, get the location
displayLocation();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
}
and it worked!!!
But I want to create a method (in another class) that get the current location and return it (instead of doing this inside activity).
So, I modified what I did above, and finished with the following:
public class UserLocation implements ConnectionCallbacks, OnConnectionFailedListener {
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
public HashMap<String, Double> getUserLocation(Activity act) {
HashMap<String, Double> getLocation = new HashMap<>();
if (checkPlayServices(act)) {
buildGoogleApiClient(act);
}
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
getLocation.put("latitude", latitude);
getLocation.put("longitude", longitude);
return getLocation;
} else {
Log.i("FAIL: ", "(Couldn't get the location. Make sure location is enabled on the device)");
return null;
}
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient(Activity act) {
mGoogleApiClient = new GoogleApiClient.Builder(act)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices(Activity act) {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(act);
if (resultCode != ConnectionResult.SUCCESS) {
return false;
}
return true;
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i("Fail: ", "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
}
And I call it from the main Activity this way:
HashMap<String, Double> userLoc = ul.getUserLocation(this);
ul.getUserLocation(getActivity());
But with this new class, I don't get the location... I debuged, and saw that mLastLocation is always null...
Can somebody tell me what I'm doing wrong?
In the activity you get last location after Google API client connected and it is right. In UserLocation class you are trying to get location before connection established and it is wrong.
From the docs:
If not connected null will be returned.
You need to move getting location in onConnected() method and somehow notify the activity. You can create callback for it or simply let the activity implement ConnectionCallbacks instead of UserLocation.
Here, GPS takes half an hour or more (time) to get the current location coordinates.
How can I use GPS from GPS_SATELLITES and GPS _NETWORK_PROVIDERS
simultaneously in the same context and get the value of the recent
GPS?
public class ImageFile extends Activity{
LocationListener listner;
Location location;
LocationManager locationManager ;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
private static final long MIN_TIME_BW_UPDATES = 1000 * 10 * 1; // 1 minute
#Override
protected void onCreate(final Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.branchreport_layout);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listner = new MyLocationListner();
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(isGPSEnabled==false&&isNetworkEnabled==false)
{
showSettingsAlert();
}
if (isGPSEnabled)
{
progress = ProgressDialog.show(this, "GPS",
"Fetching latitude and longitude...", true);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES,listner);
}
else if (isNetworkEnabled)
{
progress = ProgressDialog.show(this, "GPS",
"Fetching latitude and longitude...", true);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES,listner);
}
public class MyLocationListner implements LocationListener {
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
x = location.getLatitude();
y = location.getLongitude();
if((x!=0) && (y!=0))
{
progress.dismiss();
locationManager.removeUpdates(listner);
Geocoder gCoder = new Geocoder(ImageFile.this);
try {
addresses = gCoder.getFromLocation(x, y, 1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (addresses != null && addresses.size() > 0) {
Log.d("TestTag", "Locality: " + addresses.get(0).getLocality()+"getAddressLine"+addresses.get(0).getAddressLine(0)+",getAdminArea"+addresses.get(0).getAdminArea()+",getSubLocality"+addresses.get(0).getSubLocality());
}
}
}
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
}
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
}
GPS is always slow, so i'll suggest to use Android Location API using Google Play Services.
Steps
First check for availability of Google Play Services by calling in onResume() of the Activity
Once play services are available on the device, build the GoogleApiClient.
Connect to google api client by calling mGoogleApiClient.connect() in onStart() method. By calling this, onConnectionFailed(), onConnected() and onConnectionSuspended() (GooglePlayServiceListeners) will be triggered depending upon the connection status.
Once google api is successfully connected, displayLocation() should be called in onConnected() method to get the current location.
This is how we build the GoogleApiClient
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
displayLocation()
private void displayLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
lblLocation.setText(latitude + ", " + longitude);
} else {
lblLocation
.setText("(Couldn't get the location. Make sure location is enabled on the device)");
}
}
A perfect explanation of the above methods and steps can be found here .also check the official documentation
I followed the developer.android.com documentation and created the following code to obtain location using the Play Services. All is well except that when I test the Lattitude and Longitude obtained using - http://maps.googleapis.com/maps/api/geocode/json?latlng=latitudevalue,longitudevalue I'm getting the wrong place.
Since the code doesnot give out any error, I'm at loss as to how to find why Play services is making the error !!
Here's my code
public class MainActivity extends Activity implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener{
//Location Objects
LocationClient mLocationClient;
LocationRequest mLocationRequest;
Location mCurrentLocation;
TextView txtLong, txtLat;
static final int REQUEST_CODE_RECOVER_PLAY_SERVICES = 1001;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Getting reference to the TextView
txtLong = (TextView) findViewById(R.id.txtLong);
txtLat = (TextView) findViewById(R.id.txtLat);
//Creating LocationClient
mLocationClient = new LocationClient(this, this, this);
//Creating and setting LocationRequest for Location Update
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
//Set the update interval to 5 seconds
mLocationRequest.setInterval(1000*5);
//Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(1000*1);
}
/*#Override
protected void onStart() {
super.onStart();
}*/
#Override
protected void onResume() {
super.onResume();
if(checkPlayServices()){
//Connecting the client
mLocationClient.connect();
}
}
private boolean checkPlayServices() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(status != ConnectionResult.SUCCESS) {
if(GooglePlayServicesUtil.isUserRecoverableError(status)) {
showErrorDialog(status);
}else {
Toast.makeText(this, "This Device is not Supported", Toast.LENGTH_LONG).show();
finish();
}
return false;
}
return true;
}
private void showErrorDialog(int status) {
GooglePlayServicesUtil.getErrorDialog(status, this, REQUEST_CODE_RECOVER_PLAY_SERVICES).show();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode){
case REQUEST_CODE_RECOVER_PLAY_SERVICES:
if(resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Google Play Services must be installed", Toast.LENGTH_LONG).show();
finish();
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onStop() {
super.onStop();
//Disconnecting the client thereby invalidating it
mLocationClient.disconnect();
}
//Implemented by PlayserviceClient.ConnecitonCallback interface
#Override
public void onConnected(Bundle connectionHint) {
/*if(mLocationClient != null)
mLocationClient.requestLocationUpdates(mLocationRequest, this);
Toast.makeText(this ,"Connected", Toast.LENGTH_LONG).show();*/
if(mLocationClient !=null ){
mLocationClient.requestLocationUpdates(mLocationRequest, this);
Toast.makeText(this ,"Connected", Toast.LENGTH_LONG).show();
//Get the location
mCurrentLocation = mLocationClient.getLastLocation();
try{
//seting TextViews
txtLat.setText(mCurrentLocation.getLatitude()+"");
txtLong.setText(mCurrentLocation.getLongitude()+"");
}catch(NullPointerException e){
Toast.makeText(this,"Failed to Connect" , Toast.LENGTH_LONG).show();
Intent mIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(mIntent);
}
}
}
#Override
public void onDisconnected() {
Toast.makeText(this,"Disconnected" , Toast.LENGTH_LONG).show();
}
//Implemented by PlayserviceClient.onConnectionFailedListener interface
#Override
public void onConnectionFailed(ConnectionResult result) {
Toast.makeText(this, "Connection Failer", Toast.LENGTH_LONG).show();
}
//Implemented by onLocationChanged interface
#Override
public void onLocationChanged(Location location) {
Toast.makeText(this,"Location Changed" , Toast.LENGTH_LONG).show();
mCurrentLocation = mLocationClient.getLastLocation();
txtLat.setText(mCurrentLocation.getLatitude()+"");
txtLong.setText(mCurrentLocation.getLongitude()+"");
}
}
The text view was displaying Longitude first and then Latitude. The test url I was using in the browser, accepted latitude first and then Longitude. The mismatch took me from one part of the earth to another.
Anyway, its solved.
This Google Maps v2 api confuses me quite a bit. I have implemented it now in some way i would like to use it. I just have two small problems that i don't know how to go about.
Sometimes I don't get a location when i start the app with gps enabled or it takes way too long to get one.
So I would like it to always load with the internet location provider first to have a very fast location fix as well as always using the getlastknownlocation() first. Cant figure out how to go about it.
Here my code:
public class MapViewMain extends FragmentActivity implements LocationListener, LocationSource
{
private GoogleMap mMap;
private OnLocationChangedListener mListener;
private LocationManager locationManager;
final int RQS_GooglePlayServices = 1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mapviewmain);
//start power button service
Intent intent=new Intent("com.epicelements.spotnsave.START_SERVICE");
this.startService(intent);
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());
if(status!=ConnectionResult.SUCCESS){ // Google Play Services are not available
Toast.makeText(this, "Google Service not found", Toast.LENGTH_LONG).show();
int requestCode = 10;
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode);
dialog.show();
}else { // Google Play Services are available
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if(locationManager != null)
{
boolean gpsIsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean networkIsEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!gpsIsEnabled) {
// Toast.makeText(this, "GPS signal not found", Toast.LENGTH_LONG).show();
PopIt("No GPS found", "Would you like to go to the settings to activate it?");
}
if(gpsIsEnabled)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000L, 10F, this);
}
else if(networkIsEnabled)
{
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000L, 10F, this);
}
else
{
//Show an error dialog that GPS is disabled...
}
}
else
{
//Show some generic error dialog because something must have gone wrong with location manager.
}
setUpMapIfNeeded();
}
}
#Override
public void onPause()
{
if(locationManager != null)
{
locationManager.removeUpdates(this);
}
super.onPause();
}
#Override
public void onResume()
{
super.onResume();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
locationManager.getBestProvider(criteria, true);
if(mListener != null){
}
setUpMapIfNeeded();
mMap.setMyLocationEnabled(true); // Enable the my-location layer
if(locationManager != null)
{
mMap.setMyLocationEnabled(true); // Enable the my-location layer
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null)
{
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
// Check if we were successful in obtaining the map.
if (mMap != null)
{
setUpMap();
}
//This is how you register the LocationSource
mMap.setLocationSource(this);
}
}
/**
* This is where we can add markers or lines, add listeners or move the camera.
* <p>
* This should only be called once and when we are sure that {#link #mMap} is not null.
*/
private void setUpMap()
{
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
mMap.setPadding(0,60,0,150);
Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE);
}
#Override
public void activate(OnLocationChangedListener listener)
{
mListener = listener;
}
#Override
public void deactivate()
{
mListener = null;
}
#Override
public void onLocationChanged(Location location)
{
if( mListener != null )
{
mListener.onLocationChanged( location );
double lat = location.getLatitude();
double lng = location.getLongitude();
LatLng coordinate = new LatLng(lat, lng);
//save coordinate
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
Editor editor = pref.edit();
editor.putFloat("lat", (float) location.getLatitude());
editor.putFloat("lng", (float) location.getLongitude());
editor.putFloat("accuracy", (float) location.getAccuracy());
editor.commit();
//marker stuff
mMap.clear();
mMap.addMarker(new MarkerOptions()
.position(coordinate)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker)));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(coordinate, 16));
}
}
#Override
public void onProviderDisabled(String provider)
{
// TODO Auto-generated method stub
// Toast.makeText(this, "provider disabled", Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderEnabled(String provider)
{
// TODO Auto-generated method stub
// Toast.makeText(this, "provider enabled", Toast.LENGTH_SHORT).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
// TODO Auto-generated method stub
// Toast.makeText(this, "status changed", Toast.LENGTH_SHORT).show();
}
// Alarm Dialog if GPS not enabled
public void PopIt( String title, String message ){
new AlertDialog.Builder(this)
.setTitle( title )
.setMessage( message )
.setCancelable(false)
.setPositiveButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
//do stuff onclick of YES
//AlertDialog.dismiss();
}
})
.setNegativeButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
//do stuff onclick of CANCEL
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
}).show();
}
}
You can use LocationClient for your purpose its give LastLocation very fast.
first declare class variable
private LocationClient client;
after in onCreate
try {
if (map == null) {
MapsInitializer.initialize(this);
client = new LocationClient(this, new ConnectionCallbacks() {
#Override
public void onDisconnected() {
// TODO Auto-generated method stub
}
#Override
public void onConnected(Bundle connectionHint) {
// TODO Auto-generated method stub
Toast.makeText(MotoFreightHomeMapMainActivity.this,
"onConnected", Toast.LENGTH_LONG).show();
Location currentLocation = client.getLastLocation();
if (currentLocation != null) {
//do you stuff here
}
}
}, new OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
}
});
client.connect();
}
} catch (GooglePlayServicesNotAvailableException e) {
// TODO handle this situation
etMap.setVisibility(View.INVISIBLE);
btnEditLocation.setVisibility(View.INVISIBLE);
Toast.makeText(this, "Please install Google Play Library",
Toast.LENGTH_SHORT).show();
}
see full code here
http://developer.android.com/training/location/retrieve-current.html
You can find a sample and tutorial from here.