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
Related
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;
}
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() ).
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();
}
}
I need to get current location using seperate class which not in the Activity. This is my code and it doesnt't work. Anyone have idea to fix this.This application is always crash when I try to get location details.
package com.example.ishanfx.departmentapp.network;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class LocationHandler implements LocationListener,GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private LocationManager locationManager;
Location mLastLocation;
LocationRequest mLocationRequest;
private String latitude;
private String longitude;
Context context;
private static GoogleApiClient mGoogleApiClient;
public LocationHandler(Context context) {
this.context = context;
locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
private void setMostRecentLocation(Location lastKnownLocation) {
}
public String getLatitude() {
return latitude;
}
public String getLongitude() {
return longitude;
}
#Override
public void onLocationChanged(Location location) {
double lon = (double) (location.getLongitude());
double lat = (double) (location.getLatitude());
latitude = lat + "";
longitude = lon + "";
}
/*
* (non-Javadoc)
*
* #see
* android.location.LocationListener#onProviderDisabled(java.lang.String)
*/
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* #see
* android.location.LocationListener#onProviderEnabled(java.lang.String)
*/
#Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
#Override
public void onConnected(Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
latitude =String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
This is the mainActivity.When I call this application will crash.
LocationHandler appLocationManager = new LocationHandler(HomeActivity.this);
Toast.makeText(getApplicationContext(), appLocationManager.getLatitude().toString(), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), appLocationManager.getLongitude().toString(), Toast.LENGTH_SHORT).show();
This is the Log
FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.ishanfx.departmentapp.HomeActivity.onOptionsItemSelected(HomeActivity.java:172)
at android.app.Activity.onMenuItemSelected(Activity.java:2502)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:361)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:147)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:68)
at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:172)
at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:760)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948)
at android.support.v7.view.menu.MenuPopupHelper.onItemClick(MenuPopupHelper.java:191)
at android.widget.AdapterView.performItemClick(AdapterView.java:292)
at android.widget.AbsListView.performItemClick(AbsListView.java:1065)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2522)
at android.widget.AbsListView$1.run(AbsListView.java:3183)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4441)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
I have updated above class in a clean way.
public class LocationHandler implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private Context mContext;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private OnLocationUpdateListener onLocationUpdateListener;
public LocationHandler(Context mContext) {
this.mContext = mContext;
buildGoogleApiClient();
createLocationRequest();
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
public void startLocationUpdates(Context mContext) {
if (ActivityCompat.checkSelfPermission(mContext,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mContext,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
private void stopLocationUpdate(Context mContext) {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
//other new Methods but not using right now..
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);//set the interval in which you want to get locations
mLocationRequest.setFastestInterval(5000);//if a location is available sooner you can get it (i.e. another app is using the location services)
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
startLocationUpdates(mContext);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
if(mGoogleApiClient.isConnected() && onLocationUpdateListener != null){
onLocationUpdateListener.onLocationChange(location);
}
}
public void setOnLocationUpdateListener(OnLocationUpdateListener onLocationUpdateListener) {
this.onLocationUpdateListener = onLocationUpdateListener;
}
}
where OnLocationUpdateListener is
public interface OnLocationUpdateListener {
void onLocationChange(Location location);
void onError(EnumUtil.ErrorType errorType);
}
It takes a little time for the onConnected event to fire.
You need to give it a little time before making your toasts.
I'd add an isConnected property to your LocationHandler class like so:
private boolean isconnected = false;
public boolean isConnected() {
return isconnected;
}
#Override
public void onConnected(Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
latitude =String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
}
this.isconnected = true;
}
Then in MainActivity
LocationHandler appLocationManager = new LocationHandler(HomeActivity.this);
while(!appLocationManager.isConnected()) {
// wait for a bit
}
if (appLocationManager.isConnected()) {
Toast.makeText(getApplicationContext(), appLocationManager.getLatitude().toString(), Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), appLocationManager.getLongitude().toString(), Toast.LENGTH_SHORT).show();
}
You have to set the value of latitude and longitude using setter and then get using getter.. since no value is getting set the getter is returning null value thus null pointer exception.
Here is another solution with FusedLocationProviderClient as FusedLocationApi is deprecated.
public class LocationHandler {
private Activity activity;
private FusedLocationProviderClient mFusedLocationProviderClient;
private Location mLastKnownLocation;
private LocationCallback mLocationCallback;
private LocationRequest mLocationRequest;
private OnLocationUpdateListener onLocationUpdateListener;
private boolean updateStartedInternally = false;
public LocationHandler(Activity activity, OnLocationUpdateListener onLocationUpdateListener) {
this.activity = activity;
this.onLocationUpdateListener = onLocationUpdateListener;
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity);
createLocationRequest();
getDeviceLocation();
mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
List<Location> locationList = locationResult.getLocations();
if (locationList.size() > 0) {
//The last location in the list is the newest
Location location = locationList.get(locationList.size() - 1);
mLastKnownLocation = location;
if (onLocationUpdateListener != null) {
onLocationUpdateListener.onLocationChange(location);
if(updateStartedInternally){
stopLocationUpdate();
}
}
}
}
};
}
private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
Task locationResult = mFusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(activity, task -> {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
mLastKnownLocation = (Location) task.getResult();
if (mLastKnownLocation == null) {
updateStartedInternally = true;
mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
} else {
onLocationUpdateListener.onLocationChange(mLastKnownLocation);
}
} else {
onLocationUpdateListener.onError("Can't get Location");
}
});
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
onLocationUpdateListener.onError(e.getMessage());
}
}
public void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
updateStartedInternally = false;
mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
private void stopLocationUpdate() {
mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback);
}
//other new Methods but not using right now..
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);//set the interval in which you want to get locations
mLocationRequest.setFastestInterval(5000);//if a location is available sooner you can get it (i.e. another app is using the location services)
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
}
where OnLocationUpdateListener is
public interface OnLocationUpdateListener {
void onLocationChange(Location location);
void onError(String error);
}
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.