I am using google fused location API and I was able to successfully implement it but it appears like this I have the logs:
Location[fused 31******,30****** acc=27 et=+16h8m55s272ms]
I can't figure the problem.
i managed to get it by casting it to double
Double.toString(location.getLatitude())
This is Location Service which runs in background and Tested
public class LocationTrackingService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
protected static final String TAG = "location-updates-sample";
private Context context;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
protected Location mCurrentLocation;
protected Boolean mRequestingLocationUpdates;
private String locationIntent;
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to GoogleApiClient");
if (mCurrentLocation == null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.disconnect();
}
#Override
public void onLocationChanged(Location location) {
if (locationIntent.equals(AppConstants.LOCATION_INTENT)) {
EventBus.getDefault().post(new CurrentLocation(location));
Log.e(TAG, "LOCATION CHANGED : " + " " + DateFormat.getTimeInstance().format(new Date()) + " " + location.getLatitude() + " " + location.getLongitude());
//stopLocationUpdates();
//mGoogleApiClient.disconnect();
} else if (location.equals(AppConstants.LOCATION_TRACK_INTENT)) {
startLocationUpdates();
Log.e(TAG, "TRACK LOCATION : " + " " + DateFormat.getTimeInstance().format(new Date()) + " " + location.getLatitude() + " " + location.getLongitude());
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
buildGoogleApiClient();
mGoogleApiClient.connect();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
context = this;
locationIntent = intent.getStringExtra(AppConstants.LOCATION_INTENT);
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
}
return START_STICKY;
}
#Override
public void onDestroy() {
// handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
Log.e("STOP_SERVICE", "STOP_SERVICE");
stopLocationUpdates();
mGoogleApiClient.disconnect();
}
#Override
public void onCreate() {
super.onCreate();
buildGoogleApiClient();
mGoogleApiClient.connect();
Toast.makeText(this, "service", Toast.LENGTH_LONG).show();
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.e(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
/**
* Sets up the location request. Android has two location request settings:
* {#code ACCESS_COARSE_LOCATION} and {#code ACCESS_FINE_LOCATION}. These settings control
* the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
* the AndroidManifest.xml.
* <p>
* When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
* interval (5 seconds), the Fused Location Provider API returns location updates that are
* accurate to within a few feet.
* <p>
* These settings are appropriate for mapping applications that show real-time location
* updates.
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
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;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
mRequestingLocationUpdates = true;
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}}
Related
I'm using GoogleApiClient to implement a location listener service, but the GPS icon is always being displayed, even with the service in background. How to disable the GPS icon when the service is in the background?
Follow the sources below:
Activity
public class ShowDistanceActivity extends AppCompatActivity implements ILocationConstants {
protected static final String TAG = ShowDistanceActivity.class.getSimpleName();
#Bind(R.id.tvLocationData)
TextView tvLocationData;
#Bind(R.id.toolbar)
Toolbar toolbar;
/**
* Receiver listening to Location updates and updating UI in activity
*/
private LocationReceiver locationReceiver;
/**
* Permission util with callback mechanism to avoid boilerplate code
* <p/>
* https://github.com/kayvannj/PermissionUtil
*/
private PermissionUtil.PermissionRequestObject mBothPermissionRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_distance);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
locationReceiver = new LocationReceiver();
}
private void startLocationService() {
Intent serviceIntent = new Intent(this, LocationService.class);
startService(serviceIntent);
}
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(locationReceiver, new IntentFilter(LOACTION_ACTION));
/**
* Runtime permissions are required on Android M and above to access User's location
*/
if (AppUtils.hasM() && !(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
askPermissions();
} else {
startLocationService();
}
}
/**
* Ask user for permissions to access GPS location on Android M
*/
public void askPermissions() {
mBothPermissionRequest =
PermissionUtil.with(this).request(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION).onResult(
new Func2() {
#Override
protected void call(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
startLocationService();
} else {
Toast.makeText(ShowDistanceActivity.this, R.string.permission_denied, Toast.LENGTH_LONG).show();
}
}
}).ask(PERMISSION_ACCESS_LOCATION_CODE);
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(locationReceiver);
}
private class LocationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (null != intent && intent.getAction().equals(LOACTION_ACTION)) {
String locationData = intent.getStringExtra(LOCATION_MESSAGE);
tvLocationData.setText(locationData);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (null != mBothPermissionRequest) {
mBothPermissionRequest.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Service
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, ILocationConstants, IPreferenceConstants {
private static final String TAG = LocationService.class.getSimpleName();
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
private String mLatitudeLabel;
private String mLongitudeLabel;
private String mLastUpdateTimeLabel;
private String mDistance;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
private Location oldLocation;
private Location newLocation;
private AppPreferences appPreferences;
/**
* Total distance covered
*/
private float distance;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
appPreferences = new AppPreferences(this);
oldLocation = new Location("Point A");
newLocation = new Location("Point B");
mLatitudeLabel = getString(R.string.latitude_label);
mLongitudeLabel = getString(R.string.longitude_label);
mLastUpdateTimeLabel = getString(R.string.last_update_time_label);
mDistance = getString(R.string.distance);
mLastUpdateTime = "";
distance = appPreferences.getFloat(PREF_DISTANCE, 0);
Log.d(TAG, "onCreate Distance: " + distance);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand called");
buildGoogleApiClient();
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
return Service.START_STICKY;
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.d(TAG, "buildGoogleApiClient() called");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
protected void createLocationRequest() {
Log.d(TAG, "createLocationRequest() called");
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
try {
Log.d(TAG, "startLocationUpdates called");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
} catch (SecurityException ex) {
ex.printStackTrace();
}
}
/**
* Updates the latitude, the longitude, and the last location time in the UI.
*/
private void updateUI() {
if (null != mCurrentLocation) {
StringBuilder sbLocationData = new StringBuilder();
sbLocationData.append(mLatitudeLabel)
.append(" ")
.append(mCurrentLocation.getLatitude())
.append("\n")
.append(mLongitudeLabel)
.append(" ")
.append(mCurrentLocation.getLongitude())
.append("\n")
.append(mLastUpdateTimeLabel)
.append(" ")
.append(mLastUpdateTime)
.append("\n")
.append(mDistance)
.append(" ")
.append(getUpdatedDistance())
.append(" meters");
/*
* update preference with latest value of distance
*/
appPreferences.putFloat(PREF_DISTANCE, distance);
Log.d(TAG, "Location Data:\n" + sbLocationData.toString());
sendLocationBroadcast(sbLocationData.toString());
} else {
Toast.makeText(this, R.string.unable_to_find_location, Toast.LENGTH_SHORT).show();
}
}
/**
* Send broadcast using LocalBroadcastManager to update UI in activity
*
* #param sbLocationData
*/
private void sendLocationBroadcast(String sbLocationData) {
Log.d(TAG, "sendLocationBroadcast() called");
Intent locationIntent = new Intent();
locationIntent.setAction(LOACTION_ACTION);
locationIntent.putExtra(LOCATION_MESSAGE, sbLocationData);
LocalBroadcastManager.getInstance(this).sendBroadcast(locationIntent);
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
Log.d(TAG, "stopLocationUpdates() called");
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy() called");
appPreferences.putFloat(PREF_DISTANCE, distance);
stopLocationUpdates();
mGoogleApiClient.disconnect();
Log.d(TAG, "onDestroy Distance " + distance);
super.onDestroy();
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) throws SecurityException {
Log.i(TAG, "Connected to GoogleApiClient");
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
startLocationUpdates();
}
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged() called");
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
#Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "onConnectionSuspended() called");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
private float getUpdatedDistance() {
/**
* There is 68% chance that user is with in 100m from this location.
* So neglect location updates with poor accuracy
*/
if (mCurrentLocation.getAccuracy() > ACCURACY_THRESHOLD) {
Log.d(TAG, "getUpdatedDistance() called");
return distance;
}
if (oldLocation.getLatitude() == 0 && oldLocation.getLongitude() == 0) {
oldLocation.setLatitude(mCurrentLocation.getLatitude());
oldLocation.setLongitude(mCurrentLocation.getLongitude());
newLocation.setLatitude(mCurrentLocation.getLatitude());
newLocation.setLongitude(mCurrentLocation.getLongitude());
return distance;
} else {
oldLocation.setLatitude(newLocation.getLatitude());
oldLocation.setLongitude(newLocation.getLongitude());
newLocation.setLatitude(mCurrentLocation.getLatitude());
newLocation.setLongitude(mCurrentLocation.getLongitude());
}
/**
* Calculate distance between last two geo locations
*/
distance += newLocation.distanceTo(oldLocation);
return distance;
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
Manifest
Android Manifest declaration
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.technosavy.showmedistance">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".ShowDistanceActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".service.LocationService"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
Please, any help is welcome.
To remove the GPS icon you need to use cached and wi-fi location settings (from memory). In your code make the following changes.
In Manifest, remove:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
In Service, change the following:
mLocationRequest.setInterval(10000L);
mLocationRequest.setFastestInterval(5000L);
// Do NOT use LocationRequest.PRIORITY_HIGH_ACCURACY here
// Instead use one of the other option.
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_NO_POWER);
// Remove setSmallestDisplacement() as it should not be used
// unless you are using a GPS / PRIORITY_HIGH_ACCURACY
//mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
Pretty sure this is will remove the GPS icon but you will also only get the FusedLocationApi.getLastLocation() values when the onConnected() method is called (very possible this will be low accuracy).
The onLocationChanged() method may never trigger until another application makes a location request at a higher priority or with more accuracy.
The new fused location providers take a slightly different approach compared to previous methods. Developers now choose how much battery power is used to calculate a location instead of which device components are used to calculate it. It uses any available combination of GPS, Wi-Fi, mobile networks, and onboard sensors to calculate the location.
The LocationRequest priority settings are now:
PRIORITY_NO_POWER (passively listens for location updates from other clients)
PRIORITY_LOW_POWER (~10km "city" accuracy)
PRIORITY_BALANCED_POWER_ACCURACY (~100m "block" accuracy)
PRIORITY_HIGH_ACCURACY (accurate as possible at the expense of battery life)
Google describes the LocationRequest class here: http://developer.android.com/reference/com/google/android/gms/location/LocationRequest.html
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private double currentLatitude;
private double currentLongitude;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
Button btn_start;
TextView txt_refersh;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
btn_start = (Button) findViewById(R.id.btn_start);
txt_refersh = (TextView) findViewById(R.id.txt_refersh);
btn_start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("currentLatitude", "" + currentLatitude);
Log.e("currentLongitude", "" + currentLongitude);
}
});
mGoogleApiClient = new GoogleApiClient.Builder(this)
// The next two lines tell the new client that “this” current class will handle connection stuff
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
//fourth line adds the LocationServices API endpoint from GooglePlayServices
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
}
#Override
protected void onResume() {
System.runFinalization();
Runtime.getRuntime().gc();
System.gc();
Log.e("System GC", "Called");
super.onResume();
//Now lets connect to the API
mGoogleApiClient.connect();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onPause() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
super.onPause();
Log.v(this.getClass().getSimpleName(), "onPause()");
}
#Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// 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;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
} else {
//If everything went fine lets get latitude and longitude
currentLatitude = location.getLatitude();
currentLongitude = location.getLongitude();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationRequest.setInterval(60000);
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;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
getLocationdetails(getApplicationContext());
Log.e("currentLatitude", "" + currentLatitude);
Log.e("currentLongitude", "" + currentLongitude);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
/*
* If no resolution is available, display a dialog to the
* user with the error.
*/
Log.e("Error", "Location services connection failed with code " + connectionResult.getErrorCode());
}
}
/**
* If locationChanges change lat and long
*
* #param location
*/
#Override
public void onLocationChanged(Location location) {
currentLatitude = location.getLatitude();
currentLongitude = location.getLongitude();
}
private Location getLocationdetails(Context context) {
Location location = null;
if (mGoogleApiClient != null) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return null;
} else {
Log.e("currentLatitude", "" + currentLatitude);
Log.e("currentLongitude", "" + currentLongitude);
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
}
return location;
}
I use locationRequest.setInterval (60000); for refreshing my location but it is still not refreshing. What should I do more to get the current Latitude and Longitude every after 10 mins. I just wanted to get the log of lat long every after 10 mins.
I have following LocationService.java service class.
public class LocationService extends Service
implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final long INTERVAL = 1000 * 60;
private static final long FASTEST_INTERVAL = 1000 * 5;
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
String lat, lon;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mGoogleApiClient.connect();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
lat = String.valueOf(mLastLocation.getLatitude());
lon = String.valueOf(mLastLocation.getLongitude());
Util.WriteSharePrefrence(getApplicationContext(), "track_lat", "" + lat);
Util.WriteSharePrefrence(getApplicationContext(), "track_lng", "" + lon);
}
}
#Override
public void onCreate() {
int permissionCheck = ContextCompat.checkSelfPermission(LocationService.this, Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
//Execute location service call if user has explicitly granted ACCESS_FINE_LOCATION..
buildGoogleApiClient();
}
}
#Override
public void onConnectionSuspended(int i) {
}
synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Util.WriteSharePrefrence(getApplicationContext(), "track_lat", "" + location.getLatitude());
Util.WriteSharePrefrence(getApplicationContext(), "track_lng", "" + location.getLongitude());
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
buildGoogleApiClient();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
In the above location service what I am doing is.
1. Set fastest interval to refresh the location every 5 sec.
2. Once location availabe onLocationChanged() will be take place. Inside onLocationChanged() method I am writing current latitude and longitude in the shared preference.
3. This service will be running 24 hours in the background to get current location.
I have Mentioned both location condition in my manifest like below:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
My Issue is :
Some times onLocationChanged() method taking wrong latitude longitude
for example : user device in India and it taking USA address. The device version is Xolo - 4.2.1.(India)
Is it device specific issue? Or something I need to change in my code?
What should I do to make my location service better ?
Use Network or GPS providers or Passive if you want
public void Request_LocationUpdate(String type)
{
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, 12);
}
else
{
LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
switch (type)
{
case "Passive":
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,10000,10,locationListener);
break;
case "GPS":
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,10000,10,locationListener);
break;
case "Network":
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,10000,10,locationListener);
break;
}
}
}
all i am trying to get the location of the device but it always returns null. I know for the first time it will return null but again and again it is returning null. Below is my code. Please help me to solve this .
public class LocationHelper implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationService";
private static final long INTERVAL = 1000 * 5;
private static final long FASTEST_INTERVAL = 1000 * 3;
Context context;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
String mLastUpdateTime;
LocationUpdateListener locationUpdateListener;
public LocationHelper(Context context, LocationUpdateListener locationUpdateListener) {
this.context = context;
this.locationUpdateListener = locationUpdateListener;
if (!isGooglePlayServicesAvailable()) {
} else {
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
}
/**
* Create the location request
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
if (ConnectionResult.SUCCESS == status) {
return true;
}else if(status == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED){
Log.d(TAG, "please udpate your google play service");
Log.d(TAG, "please udpate your google play service");
Log.d(TAG, "please udpate your google play service");
return true;
}else {
// GooglePlayServicesUtil.getErrorDialog(status, getBaseContext(), 0).show();
Log.d(TAG, "google play services is not available - ...............:");
return false;
}
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
private void startLocationUpdates() {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.d(TAG, "Location update started ..............: ");
fetchLocation();
Log.d(TAG, "Location update started ..............: ");
Log.d(TAG, "Location update started ..............: ");
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
fetchLocation();
Log.v("onLocationChanged","onLocationChanged");
Log.v("onLocationChanged","onLocationChanged");
Log.v("onLocationChanged","onLocationChanged");
}
//Get the location
private void fetchLocation(){
while (mCurrentLocation == null) {
try {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Log.d(TAG, "Location null ");
Thread.sleep(2000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
if (mCurrentLocation != null) {
locationUpdateListener.locationUpdate(mCurrentLocation);
}
}
}
Thanks in advance
It seems, that you try to get last location when your LocationClient connected. But you need to request a location update to receive your current location instead of calling getLastLocation(). You created your own LocationRequest in createLocationRequest() method but you haven't ever used it in code.
Example code:
LocationServices.FusedLocationApi.requestLocationUpdates(yourGoogleApiClient, yourLocationRequest, yourLocationListener);
Update:
End when you received new location in yourLocationListener you need to you have to stop receiving location updates:
private LocationListener mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.v("onLocationChanged","onLocationChanged");
if(mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mLocationListener);
mGoogleApiClient.disconnect();
}
//your code here }
};
More details you can find here.
Hope it will help you.
Can this code be turned into an service which can be called from a activity using a button so that it runs in background even when the app i not running? If so how? I want to make an on/off switch in a separate class which will control the Service and get location data from it.
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener {
// 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;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters
// 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();
createLocationRequest();
}
// Show location button click listener
btnShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayLocation();
}
});
// Toggling the periodic location updates
btnStartLocationUpdates.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
togglePeriodicLocationUpdates();
}
});
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
// Resuming the periodic location updates
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
/**
* 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)");
}
}
/**
* Method to toggle periodic location updates
* */
private void togglePeriodicLocationUpdates() {
if (!mRequestingLocationUpdates) {
// Changing the button text
btnStartLocationUpdates
.setText(getString(R.string.btn_stop_location_updates));
mRequestingLocationUpdates = true;
// Starting the location updates
startLocationUpdates();
Log.d(TAG, "Periodic location updates started!");
} else {
// Changing the button text
btnStartLocationUpdates
.setText(getString(R.string.btn_start_location_updates));
mRequestingLocationUpdates = false;
// Stopping the location updates
stopLocationUpdates();
Log.d(TAG, "Periodic location updates stopped!");
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Creating location request object
* */
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* 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;
}
/**
* Starting the location updates
* */
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
/**
* 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();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
// Displaying the new location on UI
displayLocation();
}
Instead of
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
you can use
public abstract PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)
that accepts PendingIntent as a last argument.
Your code will look like follows:
PendingIntent serviceIntent = PendingIntent(
context, requestCode, new Intent(context, MyService.class), 0/*flag*/);
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, serviceIntent);
You also need to implement MyService by extending IntentService and add it to AndroidManifest.