2

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);
    }
}
                                                     .
Amrita Stha
  • 2,973
  • 3
  • 25
  • 46
  • Getting null or not getting location is not about using JosSchduler, Service or FusedLocationApi inside an Activity. Best way to test this is using a LocationManager with GPS and GpsStatusListener to display satellites on the view and used on the fix and SNR of the satellites. Sometimes satellites are not useable and it may return null but you should test this with FLP to see for yourself. It uses Gps same way LocationManager uses it. – Thracian Oct 18 '17 at 06:06
  • sorry i didnot get you. what do you mean by "test this with FLP to see for yourself" ? – Amrita Stha Oct 20 '17 at 03:59
  • FusedLocationApi is buggy and it gives null location sometimes. – NinjaCoder Nov 01 '17 at 20:05

1 Answers1

1

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

AbhayBohra
  • 2,047
  • 24
  • 36