2

I am coding an app in which a specific module requires the user's location. Now I am using Google's Fused Location API which can be found here.

The problem came when the location from the user's settings is turned off. I wrote a code which prompted to change the settings. I receive the changed settings in onActivityResult. But apparently, the fused location provider takes some time to get the location. I used the handler.postDelayed method to get location after a few seconds(which is only guesswork) and the code seems to be working fine.

So I'd like to ask, is there a better way to retrieve the location or decrease the delay?

My code is as follows:

public class MainActivity extends AppCompatActivity {

    String addressText = "";
    int LOCATION_REQUEST_CODE = 1;
    int REQUEST_CHECK_SETTINGS = 2;
    TextView latitude, longitude;
    LocationRequest mLocationRequest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        latitude = (TextView) findViewById(R.id.latitude);
        longitude = (TextView) findViewById(R.id.longitude);
        createLocationRequest();
    }

    void getLocation() {
        FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions( this,
                    new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE);
        }
        else {
            mFusedLocationClient.getLastLocation()
                    .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                        @Override
                        public void onSuccess(Location location) {
                            if (location != null) {
                                latitude.setText("Latitude : " + location.getLatitude());
                                longitude.setText("Latitude : " + location.getLongitude());
                                new GetAddress().execute(location);
                            }
                        }
                    });
        }
    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);
        SettingsClient client = LocationServices.getSettingsClient(this);
        Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
        task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
            @Override
            public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                getLocation();
            }
        });
        task.addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                if (e instanceof ResolvableApiException) {
                    try {
                        ResolvableApiException resolvable = (ResolvableApiException) e;
                        resolvable.startResolutionForResult(MainActivity.this,
                                REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException ignored) {
                    }
                }
            }
        });
    }

    class GetAddress extends AsyncTask<Location, Void, Void> {
        @Override
        protected Void doInBackground(Location... locations) {
            Location location = locations[0];
            List<Address> addresses = null;
            Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
            try
            {
                addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
            }
            catch (IOException ioException)
            {
                Toast.makeText(MainActivity.this, "Network Weak, can't fetch address", Toast.LENGTH_SHORT).show();
            }
            if (addresses == null || addresses.size()  == 0) {
                Toast.makeText(MainActivity.this, "Address not found", Toast.LENGTH_SHORT).show();
            }
            else {
                Address address = addresses.get(0);
                for(int i = 0; i <= address.getMaxAddressLineIndex(); i++)
                    addressText = addressText + System.getProperty("line.separator") + address.getAddressLine(i);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            Toast.makeText(MainActivity.this, addressText, Toast.LENGTH_SHORT).show();
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == LOCATION_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            getLocation();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CHECK_SETTINGS && resultCode == RESULT_OK)
        {
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    getLocation();
                }
            }, 5000);
        }
    }
}
Abhinav Upadhyay
  • 140
  • 1
  • 14
  • 2
    My initial reaction was to vote to close this question, based on the title. The content is vastly better, though, so I didn't. (Upvoting instead.) You may want to consider editing to rephrase the title so it's not so opinion-based (best practices). – Ken White Jan 06 '18 at 04:33
  • 1
    refer this link, this is best practice for location update with latest lifecycle aware component.https://developer.android.com/topic/libraries/architecture/lifecycle.html – KuLdip PaTel Jan 06 '18 at 04:33
  • @KuLdipPaTel, I went through the link provided by you, but that in any way does not answer my question. The problem is to replace the `handler.postDelayed()` with a better version. If I missed something in the link then please let me know how. – Abhinav Upadhyay Jan 06 '18 at 06:11

0 Answers0