0

Inspite of my best effort, I am unable to get my location correct. This is my main.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
        ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        //new SecondFragment();
        //TabLayout tabs = findViewById(R.id.tabs);
        //tabs.setupWithViewPager(viewPager);
        FloatingActionButton fab = findViewById(R.id.fab);
        FontDrawable drawable = new FontDrawable(this, R.string.fa_plus_solid, true, false);
        drawable.setTextColor(ContextCompat.getColor(this, android.R.color.white));
        fab.setImageDrawable(drawable);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        //Check permission
        if (ContextCompat.checkSelfPermission(getApplicationContext(),
                android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(getApplicationContext(),
                        android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
                            android.Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
            FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
            mFusedLocationClient.getLastLocation()
                    .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                        @Override
                        public void onSuccess(Location location) {
                            // Got last known location. In some rare situations this can be null.
                            if (location != null) {
                                latlang.Lat =location.getLatitude();
                                latlang.Lang =location.getLongitude();
                            }
                        }
                    });

        }
    }
}

the latlang is defined in another file as:

public class latlang {
    public static double Lat;
    public static double Lang;
}

If I hardcode the value here in latlang, everything is fine. But, of course I want the value of last known location.

Kindly help.

BaRud
  • 3,055
  • 7
  • 41
  • 89
  • First- did the code actually run? 0 is the default for an int if you created the variable but never set it. Second- getLastLocation doesn't always work, because the system doesn't always track your current location for battery reasons. SO it will only have a last location if something else had recently asked for location. You need to request an update to ensure a location. Thirdly- remember these take callbacks which will be called asynchronously. Don't assume the data will be ready in any particular timeframe. – Gabe Sechan Jul 30 '19 at 18:24
  • @GabeSechan: yes the code did run, both in emulator and an actual device. I was thinking here I am setting the value, but clearly it is not. ` if (location != null) { latlang.Lat =location.getLatitude(); latlang.Lang =location.getLongitude(); }` Kindly, if you have time, will you tell me how to do that? SO is full with android location problem and no two ans is similar. – BaRud Jul 30 '19 at 18:25

1 Answers1

0

The problem is that you try to get the location before the permission is granted. After calling requestPermissions() you immediately try to get location while the permission dialog is being displayed which means that the code that gets the location is being executed while you are seeing the permission dialog. This is why there is onRequestPermissionsResult function in activity that reports only after the user is done with permissions dialog. You will need to get the location in onRequestPermissionsResult().

Second problem in your code is that you are only getting location when the permission is not granted. Your code does not handle the case when permission is already granted.

Here is how you would solve this:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
     if (ContextCompat.checkSelfPermission(getApplicationContext(),
       android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
      ActivityCompat.checkSelfPermission(getApplicationContext(),
       android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
      ActivityCompat.requestPermissions(this,
       new String[] {
        android.Manifest.permission.ACCESS_FINE_LOCATION,
         android.Manifest.permission.ACCESS_COARSE_LOCATION
       }, 101);
     } else {
      fetchLocation();
     }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
     String[] permissions, int[] grantResults) {
     switch (requestCode) {
      case 101:
       {
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0 &&
         (grantResults[0] == PackageManager.PERMISSION_GRANTED ||
          grantResults[1] == PackageManager.PERMISSION_GRANTED)) {
         // permission was granted
         fetchLocation()
        } else {
         Show some error
        }
        return;
       }

       // other 'case' lines to check for other
       // permissions this app might request.
     }
    }

    public void fetchLocation() {
     FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
     mFusedLocationClient.getLastLocation()
      .addOnSuccessListener(this, new OnSuccessListener < Location > () {
       @Override
       public void onSuccess(Location location) {
        // Got last known location. In some rare situations this can be null.
        if (location != null) {
         latlang.Lat = location.getLatitude();
         latlang.Lang = location.getLongitude();
        }
       }
      });

    }

Basically, Create a separate function that gets the location. You will call this function from 2 places. First is in onCreate when the permission is granted, and second in onPermissionResult. Don't forget to handle permission errors.

Zohaib Amir
  • 3,482
  • 2
  • 11
  • 29