get location using GoogleAPIClient in Service - android

I want to get location in background so that I can fetch location from any activity/fragment. problem is I'm not getting the latitude and longitude in Service. Is there something I'm doing wrong here?
public class LocationService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = "sammy_";
private boolean currentlyProcessingLocation = false;
private LocationRequest locationRequest;
private Location mCurrentLocation;
private GoogleApiClient googleApiClient;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startTracking();
return START_NOT_STICKY;
}
private void startTracking() {
Log.d(TAG, "startTracking");
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
System.out.println("Current LAT: "+mCurrentLocation.getLatitude()+ " Current LANG: "+mCurrentLocation.getLongitude());
}
private void stopLocationUpdates() {
if (googleApiClient != null && googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
}
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
locationRequest = LocationRequest.create();
locationRequest.setInterval(1000);
locationRequest.setFastestInterval(1000);
locationRequest.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) {
return;
}*/
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed");
stopLocationUpdates();
stopSelf();
}
#Override
public void onConnectionSuspended(int i) {
Log.e(TAG, "GoogleApiClient connection has been suspend");
}
}

Take a look at Using GoogleApiClient in a service
It looks like you need to connect to the Google API (and should also move GoogleApi code to onCreate() ).

Related

Do I need to repeat requestLocationUpdates or just call it once?

I want to get location of android user frequently in background using a JobService. I have implemented FusedLocationApi and I call FusedLocationApi.requestLocationUpdates to receive updates on user location. Do I need to call this JobService frequently (using JobScheduler e.g. every 30 seconds) or I should call it just once and the requestLocationUpdates repeats the task itself?
public class LocationMonitoringService extends JobService implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = LocationMonitoringService.class.getSimpleName();
boolean isWorking = false;
boolean jobCancelled = false;
GoogleApiClient mLocationClient;
LocationRequest mLocationRequest = new LocationRequest();
#Override
public boolean onStartJob(JobParameters jobParameters) {
mLocationClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest.setInterval(30000);
mLocationRequest.setFastestInterval(5000);
int priority = LocationRequest.PRIORITY_HIGH_ACCURACY;
mLocationRequest.setPriority(priority);
mLocationClient.connect();
return true;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Log.d(TAG, "Job cancelled before being completed.");
jobCancelled = true;
boolean needsReschedule = isWorking;
jobFinished(jobParameters, needsReschedule);
return needsReschedule;
}
/*
* LOCATION CALLBACKS
*/
#Override
public void onConnected(Bundle dataBundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, this);
Log.d(TAG, "Connected to Google API");
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "Connection suspended");
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Location changed");
if (location != null) {
Log.d(TAG, "== location != null");
//Send result to Server
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Failed to connect to Google API");
}
}

Re- JobScheduler combined with FusedLocationProvider Api oftens gives null location value

I have a jobScheduler with fusedLocationApi provider. It works alright but once a while it gives null value for a no. of time (6-7 times in a sequence). I tried onLocationChanged() and LocationServices.FusedLocationApi.requestLocationUpdates(), both gives null values at same time. How can I improve it? I have set high accuracy or Gps,wifi and mobile networks as locating method in device setting. thanks in advance.
One more thing, 80% of the null value are received when there is no wifi. I think Fused Api should have worked well without wifi as well Since there is gps available, isn't it?
Main class
public class LiveTrack extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_track);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName jobService =
new ComponentName(getPackageName(), MyJobService.class.getName());
JobInfo jobInfo =
new JobInfo.Builder(MYJOBID, jobService).setPeriodic(15 * 60 * 1000L)
.setExtras(bundle)
.build();
int jobId = jobScheduler.schedule(jobInfo);
if(jobScheduler.schedule(jobInfo)>0){
Log.e("status","running");
}else{
Log.e("status","failed");
}
}
}
JobService class with fused Api Provider
public class MyJobService extends JobService
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
, LocationListener {
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
private Location mLastLocation;
public static String latitude;
public static String latitudeIfNull;
public static String longitude;
public static String longitudeIfNull;
#Override
public boolean onStartJob(JobParameters jobParameters) {
setUpLocationClientIfNeeded();
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(30000);
mLocationRequest.setFastestInterval(30000);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Toast.makeText(this,
"App has stopped working. Please open the app again. Thankyou",
Toast.LENGTH_LONG).show();
return false;
}
#Override
public void onConnected(#Nullable 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) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(this.mGoogleApiClient,mLocationRequest, this);
createLocationRequest();
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
private void setUpLocationClientIfNeeded()
{
if(mGoogleApiClient == null)
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
this.mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
this.mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
latitudeIfNull = location.getLatitude() + "";
longitudeIfNull = location.getLongitude() + "";
Log.e("gps longitude",longitudeIfNull);
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(60000);
mLocationRequest.setFastestInterval(50000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(final LocationResult locationResult) {
latitude = locationResult.getLastLocation().getLatitude() + "";
longitude = locationResult.getLastLocation().getLongitude() + "";
Log.i("latitude ", latitude + "");
Log.i("longitude ", longitude + "");
}
#Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
Log.i("onLocationAvailability", "onLocationAvailability: isLocationAvailable = " + locationAvailability.isLocationAvailable());
}
}, null);
}
}
.
Try this
Create a background service class like this
public class LocationBackGroundService extends Service implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationBackGroundService";
private static final long INTERVAL = 100;
private static final long FASTEST_INTERVAL = 100;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
Context mCOntext;
public void LocationBackGroundService(Context mContext) {
this.mCOntext = mContext;
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
mGoogleApiClient.connect();
}
#Override
public void onCreate() {
super.onCreate();
if (!isGooglePlayServicesAvailable()) {
// finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
return false;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
protected void startLocationUpdates() {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(this, "OnConnection Suspended", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this, "OnConnection Failed", Toast.LENGTH_SHORT).show();
}
#Override
public void onLocationChanged(Location location) {
if (null != mCurrentLocation) {
mCurrentLocation = location;
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
}
}
}
And call when activity starts like this
startService(new Intent(this, yourBackgroundServiceName.class));
and in menifest
<service android:name=".yourBackgroundServiceName"></service>
and don;t forget to add run time permissions before stating a service

onLocationChanged never called , GoogleApiClient

I am trying to get continuous location updates by running a background service. While I debug the code onConnected(Bundle b) is called and location update request is called. But onLocationChanged(Location location) is never called. Below is my code:
public class LocationUpdateService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient googleApiClient;
private LocationRequest mLocationRequest;
Location mCurrentLocation;
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
double lat = mCurrentLocation.getLatitude();
double lng = mCurrentLocation.getLongitude();
}
//GoogleApiClient
#Override
public void onConnectionFailed(ConnectionResult bundle) {
}
#Override
public void onConnected(Bundle bundle) {
Log.i("onConnected", "GoogleApiClient");
Toast.makeText(this, "Location service connected", Toast.LENGTH_SHORT).show();
createLocationRequest();
startLocationUpdate();
}
#Override
public void onConnectionSuspended(int i) {
}
//Service
#Override
public void onCreate() {
super.onCreate();
buildGoogleApiClient();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY; // run until explicitly stopped.
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void startLocationUpdate() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, mLocationRequest, this);
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
}
void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
void createLocationRequest() {
mLocationRequest = new LocationRequest().create()
.setInterval(5000)
.setFastestInterval(5000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
}
I can't understand where I am making mistake, while I have followed android docs. I am testing on real device and app has location permissions.
service in menifest:
<service
android:name=".locations.LocationUpdateService"
android:enabled="true"
android:exported="false"></service>
Call of service in activity:
startService(new Intent(BaseActivity.this, LocationUpdateService.class));
What is your android phone SDK and how are you asking for the permissions on the manifest file?
If your phone SDK is 23 or higher the way you ask for permissions is different.
It was just a stupid debugging issue. I found my device location Access was off in advance settings.

Calculate time between onLocationChanged method

I need to calculate time difference between every location change(onLocationChanged). What is a proper way to do that?
My code for getting user's location:
public class LocationService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private DatabaseHelpers mDatabaseHelpers;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
mDatabaseHelpers = new DatabaseHelpers(LocationService.this);
}
public void buildGoogleApiClient() {
createLocationRequest();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private String getCurrentTimeStamp() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm");
String format = simpleDateFormat.format(new Date());
return format;
}
public void startLocationUpdates() {
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;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("Location Service", "Started");
buildGoogleApiClient();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
// The service is no longer used and is being destroyed
stopLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onConnected(#Nullable Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
In the above code i am getting user's location just fine but i need to calculate time difference when onLocationChanged method gets called.
Proper way ? Just use getTime() method of Location object.
Compare new and previous locations, then take the difference.
private Location mPrevLocation;
#Override
public void onLocationChanged(Location location) {
if(mPrevLocation != null){
long prevTime = mPrevLocation.getTime();
long currentTime = location.getTime();
// This is exactly what you want
long diffTime = currentTime - prevTime ;
}
mPrevLocation = location;
}

Google api client disconnect when the app destroyed

In my project i create background service which is get location using google api client.
my problem is when app destroyed,service is running but google api client automatically disconnected and cannot get lat-lang. i don't want lost a connection.
This is my service class code
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
String lat, lon;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}else{
mGoogleApiClient.connect();
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setInterval(100); // Update location every second
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
lat = String.valueOf(mLastLocation.getLatitude());
lon = String.valueOf(mLastLocation.getLongitude());
}
updateUI();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
lat = String.valueOf(location.getLatitude());
lon = String.valueOf(location.getLongitude());
updateUI();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
buildGoogleApiClient();
}
synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
//setUpLocationClientIfNeeded();
if(!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting())
{
mGoogleApiClient.connect();
}
return START_STICKY;
}
void updateUI() {
Log.d("LatLongGPS", lat + "==========" + lon);
Toast.makeText(getApplicationContext(), "Service"+lat + "==========" + lon, Toast.LENGTH_LONG).show();
}
}

Categories

Resources