I am a windows application programmer and recently started learning android. I am planning to make an app that will send GPS coordinates periodically say after every 30 seconds after clicking "start" button and stop doing so by clicking "stop" button (I have already developed a web service accepting the data) . In windows I would use a timer and on every "tick" will find the GPS coordinates and send it. Please help in understanding how a similar thing can be done in android.
Please check how i'm using in my app and its working perfect.I'm using fused api for update location please follow few steps.
Step 1. Make this class
GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
Step2. Make this interface
LocationUpdateListener.java
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* #param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* #param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
Step 3. Call this on your oncreate
private GoogleLocationService googleLocationService;
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
and call this onDestroy
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
Hope this will help you to solve your problem.
Take a look to RxGpsService (An Android service to retrieve GPS locations and route stats using RxJava). It retrieves a RouteStats object which contains the current speed, distance, time elapsed and waypoints. Also you can play/stop the chrono in order to discard locations when chrono is stopped.
Related
I' trying to getLastLocation() in my Service, witch is starting every minute. As I can see, fusedLocation requires Activity or Executor in .addOnSuccessListener(). How I can get it in Service?
LocationCheckService.class
public class LocationCheckService extends Service{
private FusedLocationProviderClient mFusedLocationClient;
#Override
public void onCreate() {
super.onCreate();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
}
}
});
}
#SuppressLint("MissingPermission")
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
You don't need GoogleApiClient -
first in gradle add -
implementation 'com.google.android.gms:play-services-location:15.0.0'
In Android Manifest -
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
than create a service to get location update as -
public class LocationUpdateService extends Service {
private FusedLocationProviderClient client;
private LocationRequest locationRequest;
#Override
public void onCreate() {
super.onCreate();
client = LocationServices.getFusedLocationProviderClient(this);
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(0);
locationRequest.setFastestInterval(0);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
client.requestLocationUpdates(locationRequest, locationCallback, null);
} catch (SecurityException ignore) {
Log.e("AppLocationService", "SecurityException - " + ignore.toString(), ignore);
}
return START_STICKY;
}
private final LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
List<Location> locationList = locationResult.getLocations();
if (locationList.size() != 0) {
Location location = locationList.get(0);
Log.e("AppLocationService", "Latitude - " +location.getLatitude()+", longitude - " +location.getLongitude() );
}
}
};
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
}
To get update in activity you can use LocalBroadCast OR same code you can use in Activity
NOTE : don't forget to take permission above 23
I provide one separate class for fetching location data using faused API. you can call this class into your service it gets latest location lat and long value.
public class GPSController implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
OnLocationUpdateListener onLocationUpdateListener;
public final String TAG = getClass().getSimpleName();
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
GoogleApiClient googleApiClient;
LocationRequest mLocationRequest;
Location mCurrentLocation;
private static long INTERVAL = 1000 * 10;
private static long FASTEST_INTERVAL = 1000 * 5;
FragmentActivity mActivity;
private boolean isLiveUpdate = false;
PendingResult<LocationSettingsResult> result;
/**
* Checking permission and connect with Google Location service
* #param activity
*/
public GPSController(FragmentActivity activity) {
this.mActivity = activity;
if(PermissionManager.checkPermission(mActivity,PermissionManager.ACCESS_LOCATION))
{
if (!isGooglePlayServicesAvailable()) {
CustomLogHandler.printInfolog("checking googleplayservice : ", "false");
((BaseActivity)mActivity).showAlertDialog(mActivity, mActivity.getString(R.string.app_name), mActivity.getString(R.string.play_service_not_found));
} else {
CustomLogHandler.printInfolog("checking googleplayservice : ", "true");
createLocationRequest();
initFuseAPI();
}
}
else
{
PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION,mActivity);
}
}
public void connectForLocation()
{
createLocationRequest();
initFuseAPI();
}
/**
* Turn on Live update of location on given interval
* #param value
* #param INTERVAL
* #param FASTEST_INTERVAL
*/
public void turnOnLiveUpdate(boolean value,long INTERVAL,long FASTEST_INTERVAL)
{
isLiveUpdate = value;
this.INTERVAL = INTERVAL;
this.FASTEST_INTERVAL = FASTEST_INTERVAL;
}
/**
* Turn off live update of location
*/
public void turnOffLiveUpdate()
{
isLiveUpdate = false;
}
/**
* Disconnect from Google location service
*/
public void disconnect()
{
try {
Log.d(TAG, "onStop fired ..............");
googleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " +googleApiClient.isConnected());
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Resume Location update service if stopped
*/
public void onResumeUpdate()
{
try {
if(googleApiClient != null) {
if (googleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
public void setLocatonUpdateListener(OnLocationUpdateListener onLocationUpdateListener)
{
this.onLocationUpdateListener = onLocationUpdateListener;
}
/**
* Create location update request
*/
protected void createLocationRequest() {
try {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Initialize google location service
*/
void initFuseAPI()
{
try
{
googleApiClient = new GoogleApiClient.Builder(mActivity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Log.d(TAG, "initFuseAPI fired ..............");
googleApiClient.connect();
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Check Google location service is available or not
* #return
*/
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, mActivity, 0).show();
return false;
}
}
/**
* called when connected with google location service
* #param bundle
*/
#Override
public void onConnected( Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + googleApiClient.isConnected());
LocationManager manager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE );
boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(statusOfGPS) {
startLocationUpdates();
}else
{
enableGpsService();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed( ConnectionResult connectionResult) {
}
/**
* Location update received here
* #param location
*/
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
SetLocation();
}
void enableGpsService()
{
try
{
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult( LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
//already connected to GPS
startLocationUpdates();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by
// showing the user a dialog.
try {
status.startResolutionForResult(mActivity, PermissionManager.REQUEST_LOCATION);
startLocationUpdates();
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
//redirect user to setting screen, manually user can enble GPS
mActivity.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
break;
}
}
});
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Request location update service
*/
public void startLocationUpdates()
{
try {
//check required even you checked it previously
if (PermissionManager.checkPermission(mActivity, PermissionManager.ACCESS_LOCATION))
{
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
} else {
PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION, mActivity);
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Stop location update
*/
public void stopLocationUpdates() {
try {
if(googleApiClient != null) {
fusedLocationProviderApi.removeLocationUpdates(
googleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* set location values received
*/
private void SetLocation()
{
try {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
onLocationUpdateListener.onLocationUpdate(mCurrentLocation);
/**isLiveUpdate = true for Live update **/
if (!isLiveUpdate) {
fusedLocationProviderApi.removeLocationUpdates(googleApiClient,this);
}
googleApiClient.disconnect();
//mCurrentLocation.getAccuracy()
//mCurrentLocation.getProvider()
} else {
Log.d(TAG, "location is null ...............");
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
public Location getLocation(){
return mCurrentLocation;
}
public static List<Address> getAddress(Double mLat, Double mLang, Context context)
{
List<Address> addresses = null;
try
{
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
addresses = geocoder.getFromLocation(mLat, mLang, 1);
}catch (Exception e)
{
e.printStackTrace();
}
return addresses;
}
/**
* For receive location update
*/
public interface OnLocationUpdateListener {
void onLocationUpdate(Location mCurrentLocation);
}
}
call into this service class like this ..
gpsController = new GPSController(getActivity());
gpsController.setLocatonUpdateListener(this);
if (gpsController != null)
gpsController.onResumeUpdate();
public void setLocatonUpdateListener(OnLocationUpdateListener onLocationUpdateListener) {
this.onLocationUpdateListener = onLocationUpdateListener;
}
and also implement this into class ..
implements GPSController.OnLocationUpdateListener
#Override
public void onLocationUpdate(Location mCurrentLocation) {
CURRENT_LET = String.valueOf(mCurrentLocation.getLatitude());// both string variable to store value
CURRENT_LANG = String.valueOf(mCurrentLocation.getLongitude());
}
This implementation in Java works in a service class, after the fusedLocationClient has been initialized:
fusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
Location last_known_loction = task.getResult();
latitude = last_known_loction.getLatitude();
longitude = last_known_loction.getLongitude();
}
});
I would like to know how can I get my location (longitude and latitude,
I dont need a position on the map) at a certain time and in the most accurate way. For example when a disconnection between two devices happen.
I have seen many examples with the Google API but they are more focused on tracking rather than obtaining the coordinates at a certain time.
I have read in some sites that getLastKnownLocation isn`t very accurate.
Thanks in advance.
i make seperate class for get current location lat and long value.
used below class for location.
public class GPSController implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
OnLocationUpdateListener onLocationUpdateListener;
public final String TAG = getClass().getSimpleName();
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
GoogleApiClient googleApiClient;
LocationRequest mLocationRequest;
Location mCurrentLocation;
private static long INTERVAL = 1000 * 10;
private static long FASTEST_INTERVAL = 1000 * 5;
FragmentActivity mActivity;
private boolean isLiveUpdate = false;
PendingResult<LocationSettingsResult> result;
/**
* Checking permission and connect with Google Location service
* #param activity
*/
public GPSController(FragmentActivity activity) {
this.mActivity = activity;
if(PermissionManager.checkPermission(mActivity,PermissionManager.ACCESS_LOCATION))
{
if (!isGooglePlayServicesAvailable()) {
CustomLogHandler.printInfolog("checking googleplayservice : ", "false");
((BaseActivity)mActivity).showAlertDialog(mActivity, mActivity.getString(R.string.app_name), mActivity.getString(R.string.play_service_not_found));
} else {
CustomLogHandler.printInfolog("checking googleplayservice : ", "true");
createLocationRequest();
initFuseAPI();
}
}
else
{
PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION,mActivity);
}
}
public void connectForLocation()
{
createLocationRequest();
initFuseAPI();
}
/**
* Turn on Live update of location on given interval
* #param value
* #param INTERVAL
* #param FASTEST_INTERVAL
*/
public void turnOnLiveUpdate(boolean value,long INTERVAL,long FASTEST_INTERVAL)
{
isLiveUpdate = value;
this.INTERVAL = INTERVAL;
this.FASTEST_INTERVAL = FASTEST_INTERVAL;
}
/**
* Turn off live update of location
*/
public void turnOffLiveUpdate()
{
isLiveUpdate = false;
}
/**
* Disconnect from Google location service
*/
public void disconnect()
{
try {
Log.d(TAG, "onStop fired ..............");
googleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " +googleApiClient.isConnected());
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Resume Location update service if stopped
*/
public void onResumeUpdate()
{
try {
if(googleApiClient != null) {
if (googleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
public void setLocatonUpdateListener(OnLocationUpdateListener onLocationUpdateListener)
{
this.onLocationUpdateListener = onLocationUpdateListener;
}
/**
* Create location update request
*/
protected void createLocationRequest() {
try {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Initialize google location service
*/
void initFuseAPI()
{
try
{
googleApiClient = new GoogleApiClient.Builder(mActivity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Log.d(TAG, "initFuseAPI fired ..............");
googleApiClient.connect();
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Check Google location service is available or not
* #return
*/
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, mActivity, 0).show();
return false;
}
}
/**
* called when connected with google location service
* #param bundle
*/
#Override
public void onConnected( Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + googleApiClient.isConnected());
LocationManager manager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE );
boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(statusOfGPS) {
startLocationUpdates();
}else
{
enableGpsService();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed( ConnectionResult connectionResult) {
}
/**
* Location update received here
* #param location
*/
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
SetLocation();
}
void enableGpsService()
{
try
{
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult( LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
//already connected to GPS
startLocationUpdates();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by
// showing the user a dialog.
try {
status.startResolutionForResult(mActivity, PermissionManager.REQUEST_LOCATION);
startLocationUpdates();
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
//redirect user to setting screen, manually user can enble GPS
mActivity.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
break;
}
}
});
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Request location update service
*/
public void startLocationUpdates()
{
try {
//check required even you checked it previously
if (PermissionManager.checkPermission(mActivity, PermissionManager.ACCESS_LOCATION))
{
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
} else {
PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION, mActivity);
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Stop location update
*/
public void stopLocationUpdates() {
try {
if(googleApiClient != null) {
fusedLocationProviderApi.removeLocationUpdates(
googleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* set location values received
*/
private void SetLocation()
{
try {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
onLocationUpdateListener.onLocationUpdate(mCurrentLocation);
/**isLiveUpdate = true for Live update **/
if (!isLiveUpdate) {
fusedLocationProviderApi.removeLocationUpdates(googleApiClient,this);
}
googleApiClient.disconnect();
//mCurrentLocation.getAccuracy()
//mCurrentLocation.getProvider()
} else {
Log.d(TAG, "location is null ...............");
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
public Location getLocation(){
return mCurrentLocation;
}
public static List<Address> getAddress(Double mLat, Double mLang, Context context)
{
List<Address> addresses = null;
try
{
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
addresses = geocoder.getFromLocation(mLat, mLang, 1);
}catch (Exception e)
{
e.printStackTrace();
}
return addresses;
}
/**
* For receive location update
*/
public interface OnLocationUpdateListener {
void onLocationUpdate(Location mCurrentLocation);
}
}
then used in activity class like below...
private GPSController gpsController;
#Override
public void onStop() {
super.onStop();
if (gpsController != null)
gpsController.disconnect();
}
#Override
public void onPause() {
super.onPause();
if (gpsController != null)
gpsController.stopLocationUpdates();
}
#Override
public void onResume() {
super.onResume();
gpsController = new GPSController(getActivity());
gpsController.setLocatonUpdateListener(this);
if (gpsController != null)
gpsController.onResumeUpdate();
}
#Override
public void onLocationUpdate(Location mCurrentLocation) {
CURRENT_LET = String.valueOf(mCurrentLocation.getLatitude());
CURRENT_LANG = String.valueOf(mCurrentLocation.getLongitude());
loadMoreItems();
}
also pl note activity class implement this below interface ..
implements GPSController.OnLocationUpdateListener
and you can remove permission code if you not required.
add also add two permission into manifest file..
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
I want to get location updates on a "background service" using latest fused location provider client.I don't want to use the location listeners and Google API Client that all are using.
I also need to use location settings Api provided by google play services to check whether location setting are disable or enable on that "background service".Please help.
if we need to use fusion location api then we need to use Google API client, For the background service it is not an issue to use it, Following is the example which I used for getting location update in background, But one more thing as Google introduces 'DOZE' mode from 6.0 so I can not give surety give update when your device in 'DOZE' mode,
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
/**
* Created By Dhaval Solanki
*/
public class ConnectionService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
String TAG = "ConnectionService";
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location previousLocation;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private Location mLastLocation;
private Context context;
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = getApplicationContext();
Log.i(TAG, "onStartCommand");
if (checkPermsion(context)) {
setupLocationService(context);
}
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
ApplicationCLass.isServiceRunning = true;
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
ApplicationCLass.isServiceRunning = false;
return super.onUnbind(intent);
}
#Override
public void onDestroy() {
ApplicationCLass.isServiceRunning = false;
super.onDestroy();
}
private void setupLocationService(Context context) {
if (checkPlayServices()) {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
createLocationRequest();
}
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest().create();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mGoogleApiClient.connect();
}
public boolean checkPermsion(Context context) {
int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
} else if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
} else {
return true;
}
} else {
return true;
}
}
private boolean checkPlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result = googleAPI.isGooglePlayServicesAvailable(this);
if (result != ConnectionResult.SUCCESS) {
return false;
}
return true;
}
private void startLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (Prefs.getUserLat(context).trim().length() > 0 && Prefs.getUserLong(context).trim().length() > 0) {
} else {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
Prefs.setUserLat(context, String.valueOf(mLastLocation.getLatitude()));
Prefs.setUserLong(context, String.valueOf(mLastLocation.getLongitude()));
}
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "Connected to onConnected");
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connected to onConnectionSuspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connected to onConnectionFailed");
}
#Override
public void onLocationChanged(Location location) {
try {
Logger.print("onLocationChanged", "latitued :" + location.getLatitude() + " ,, Longitude " + location.getLongitude());
} catch (Exception e) {
e.printStackTrace();
}
}
}
One another alaram service continues runnning or not
import android.app.ActivityManager;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AlarmService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
boolean isServiceRunning = false;
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (ConnectionService.class.getName().equals(service.service.getClassName())) {
isServiceRunning = true;
break;
}
}
Log.i("AlarmService", "Service is running " + isServiceRunning);
if(!isServiceRunning) {
startService(new Intent(getApplicationContext(),ConnectionService.class));
} else {
ConnectionService.checkConnectionAndConnect(getApplicationContext());
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public AlarmService() {
super("AlaramService");
}
}
And Finaly start service
private void checkAndStartService() {
final ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
new AsyncTask<Void, Void, Boolean>() {
boolean isServiceRunning = false;
#Override
protected Boolean doInBackground(Void... params) {
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (ConnectionService.class.getName().equals(service.service.getClassName())) {
isServiceRunning = true;
break;
}
}
return isServiceRunning;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
Log.i("onPostExecute", "Service running = " + aBoolean);
if (!aBoolean) {
startService(new Intent(ActivitySplash.this, ConnectionService.class));
Intent i = new Intent(ActivitySplash.this, AlarmService.class);
PendingIntent pi = PendingIntent.getService(ActivitySplash.this, 0, i, 0);
AlarmManager am = (AlarmManager) ActivitySplash.this.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi); // cancel any existing alarms
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pi);
}
}
}.execute();
}
You can write the code for the intentService as given below. It has been considered that since it is running in the background, we would not show the permission dialogs.
public class GetLocationService extends IntentService
implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static String TAG = GetLocationService.class.getSimpleName();
private GoogleApiClient mGoogleApiClient;
public GetLocationService() {
super(TAG);
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* #param name Used to name the worker thread, important only for debugging.
*/
public GetLocationService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Log.d(TAG, "disconnecting");
mGoogleApiClient.disconnect();
}
Log.d(TAG, "onHandleIntent");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationRequest locationRequestLow = LocationRequest.create();
locationRequestLow.setPriority(LocationRequest.PRIORITY_LOW_POWER);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
} else {
Log.d(TAG, "permission denied");
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, location.toString());
}
}
You can extend the service class like
public class BackgroundLocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener
You can check the full source code here BackgroundLocationService.java
For enable location settings
private void displayLocationSettingsRequest() {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(10000 / 2);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(context, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException ignored) {
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to
startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
//startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
displayLocationSettingsRequest();//keep asking
showToast("Location permission needed");
break;
}
break;
}
}
You can check location settings from Service and if location is off ,
LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {}
if(!gps_enabled && !network_enabled) {
// notify user
// Either you can display a Notification(Recommended way) or you can show dialog with
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
//It needs SYSTEM_ALERT_WINDOW permission. Add this permission in Manifest.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
}
Hi I have good understanding about location services and how we can use in it perfect way. See i'll give you idea about fused apis.
Just make sure follow the below steps. It is pretty nice and simple.
Step 1. Make this class
GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
Step2. Make this interface
LocationUpdateListener.java
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* #param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* #param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
Step 3. Make this Location service class
LocationService.java
public class LocationService extends Service {
private GoogleLocationService googleLocationService;
#Override
public void onCreate() {
super.onCreate();
//start the handler for getting locations
//create component
updateLocation(getApplicationContext());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
//get current location os user
private void updateLocation(Context context) {
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
}
IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public LocationService getServerInstance() {
return LocationService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//stop location updates on stopping the service
#Override
public void onDestroy() {
super.onDestroy();
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
}
}
Edited Answer:
How to use service,
Start service in your main activity,like this
startService(new Intent(context, LocationService.class));
for stop,
stopService(new Intent(context, LocationService.class));
and declare in manifest like this,
<service
android:name=".service.location.LocationService"
android:enabled="true"></service>
Note: I have done this because i need location after killed the app.If you dont want service.Then,you can call directly below code in class where location need to be update and remove locationservice.
private GoogleLocationService googleLocationService;
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
and call this onDestroy
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
Remember Locationservice should be declare in manifest as well.
According to me this is the best solution.
Thanks hope this will help you
The question does not appear to be very specific. It seems like you're having trouble starting up with using location services.
The best idea would probably be checking out the Google samples (https://github.com/googlesamples/android-play-location) to better understand the mechanics.
I would probably start by implementing the simplest example (LocationUpdates). It uses the FusedLocationProvider and also checks if the settings are enabled, so it should fit your needs, or at least get you started.
If you really need to use a service you can check out LocationUpdatesForegroundService or LocationUpdatesPendingIntent. But I would strongly recommend to read and understand the first example before you do this.
I am trying to fetch lastknown location but it is giving me null value. I tested whether GPS is enabled or not, it's returning true.
Even I went into Google Maps and pointed my location (thinking that location data might be cleared) but it still didn't work.
Here is my Code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
boolean isgps=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
Log.v("is GPs Enabled",isgps+"");
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateNewLocation(location);
}
private void updateNewLocation(Location location) {
TextView myLocationText=(TextView)findViewById(R.id.myLocation);
if(location!=null){
double lat=location.getLatitude();
double lng=location.getLongitude();
myLocationText.setText("lat:"+lat+"\nlong:"+lng);
Log.v("Location","lat:"+lat+"\nlong:"+lng);
}
}
hi why trying to use getLastKnownLocation.It return your previous latitude and longitude.Most probably it retrun you null.It takes time to update and it return previous lat lng.It could be very old or new old.Its not accurate and correct. So,Its better you go for new approach.
I'm just referring you google Fused api for location any kind of updation or current.Its very accurate.
How you can fused api in your project.See i'll give you small example.
Step 1. Make this class GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
Step2. Make this interface
LocationUpdateListener.java
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* #param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* #param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
Step 3. Use this piece of code where you want to get location
private GoogleLocationService googleLocationService;
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
and call this onDestroy
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
Thanks hope this help you.
I am trying to get location of user as longitude and latitude from GPS/network which ever is available and i want to get it fast , or else previous location coordinates will return if cannot get new one right now.
Here is my attempt:
public class GPSTracker extends Service{
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
private final Context mContext;
// Declaring a Location Manager
protected LocationManager locationManager;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
Location location = null; // location
double latitude; // latitude
double longitude; // longitude
myLocationLitener locationLitener;
public GPSTracker(Context context) {
this.mContext = context;
locationLitener = new myLocationLitener();
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES,locationLitener);
Log.d("Network", "Network Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return null;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, locationLitener);
Log.d("GPS", "GPS Enabled");
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
/**
* Stop using GPS listener Calling this function will stop using GPS in your
* app
*/
public void stopUsingGPS() {
if (locationManager != null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.removeUpdates(locationLitener);
}
}
/**
* Function to get latitude
*/
public double getLatitude() {
if (location != null) {
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
if (location != null) {
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
*
* #return boolean
*/
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog On pressing Settings button will
* lauch Settings Options
*/
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// 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);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
private class myLocationLitener implements LocationListener{
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
}
How i use this class?
Suppose i am running below function in async task (who don't have knowledge of android annotation #Background is doing this)
#Background
void getmyLocationAndSend(){
GPSTracker gps = new GPSTracker(context);
// check if GPS location can get Location
if (gps.canGetLocation()) {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.d("Your Location", "latitude:" + gps.getLatitude()
+ ", longitude: " + gps.getLongitude());
latitude = gps.getLatitude(); // set the globals
longitude = gps.getLongitude(); // set the globals
}else{
showToast("Network is connected..");
if (progress != null && progress.isShowing()) {
progress.dismiss();
}
}
}else{
showToast("Cannot get location from gps..");
if (progress != null && progress.isShowing()) {
progress.dismiss();
}
}
}
my goal is to get coordinates in less than 30 seconds , and never get 0.0 value , how can i achieve that any help appreciated ?
Please check how i'm using in my app and its working perfect.I'm using fused api for update location please follow few steps.Currently you using very old approach.So, there is no need now
and pass here your time in milliseconds what you want
UPDATE_INTERVAL_IN_MILLISECONDS
Step 1. Make this class
GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
Step2. Make this interface
LocationUpdateListener.java
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* #param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* #param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
Step 3. Make this Location service class
LocationService.java
public class LocationService extends Service {
private GoogleLocationService googleLocationService;
#Override
public void onCreate() {
super.onCreate();
//start the handler for getting locations
//create component
updateLocation(getApplicationContext());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
//get current location os user
private void updateLocation(Context context) {
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
}
IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public LocationService getServerInstance() {
return LocationService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//stop location updates on stopping the service
#Override
public void onDestroy() {
super.onDestroy();
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
}
}
Edited Answer:
How to use service,
Start service in your main activity,like this
startService(new Intent(context, LocationService.class));
for stop,
stopService(new Intent(context, LocationService.class));
and declare in manifest like this,
<service
android:name=".service.location.LocationService"
android:enabled="true"></service>
Note: I have done this because i need location after killed the app.If you dont want service.Then,you can call directly below code in class where location need to be update and remove locationservice.
private GoogleLocationService googleLocationService;
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
and call this onDestroy
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
Remember Locationservice should be declare in manifest as well.
According to me this is the best solution.I have done alot of work on location.
Thanks hope this will help you
Check out FusedLocationApi. It does a great job of that and it gives you options for minimizing battery performance.
You can take a look to RxGpsService (An Android service to retrieve GPS locations and route stats using RxJava). It retrieves a RouteStats object which contains the current speed, distance, time elapsed and waypoints.
Also is customizable, so you can set your interval by using .withInterval(30000) and .withFastestInterval(30000) .