3

For my app, I need to get the location of the user, to fetch corresponding data from a server. The problem is that the code I use doesn't properly return the location when it's opened the first time. After restarting the app once it works just fine. I searched the other questions and found out, that if you use getLastKnownLocation and there is no location since the last reboot, it returns null. But why does it work when the app is restarted? Does it fetch it when it's opened the first time, and how can I make it wait until the location is fetched properly at the first opening then?

The code of my MainActivity:

if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {

  requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 123);
} else {
    progressBar.setVisibility(View.VISIBLE);
    GPSClass gt = new GPSClass(getActivity().getApplicationContext());
    Location location = gt.getLocation();

    if (location == null) {
       //Toast
    } else {
        lat = location.getLatitude();
        lon = location.getLongitude();
    }
    new GetContacts().execute();
}

And the GPSClass:

public class GPSClass implements LocationListener {

Context context;

public GPSClass(Context context) {
    super();
    this.context = context;
}

public Location getLocation(){
    if (ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) {
        Log.e("fist","error");
        return null;
    }
    try {
        LocationManager lm = (LocationManager) context.getSystemService(LOCATION_SERVICE);
        boolean isGPSEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if (isGPSEnabled){
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000,10,this);
            Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            return loc;
        }else{
            Log.e("sec","error");
        }
    }catch (Exception e){
        e.printStackTrace();
    }
    return null;
}
user9155899
  • 19
  • 1
  • 9
  • check out this link https://stackoverflow.com/questions/9873190/my-current-location-always-returns-null-how-can-i-fix-this – amit Aug 19 '18 at 09:09
  • How can I notify my MainActivity when the location has changed in the GPS class? – user9155899 Aug 19 '18 at 09:55

2 Answers2

0

Here is the full tutorial

I shared a tutorial link follow that link.

Call this below method. It will return value; when lat and long is found. Until object is null or doesn't return any value your app must be idle or show some progress value or tell the user to wait.

InitGeoLocationUpdate.locationInit(SplashScreen.this,
    object -> {
        double latitude = object.latitude;
        double longitude = object.longitude;
        Lg.INSTANCE.d(TAG, "Current Location Latitude: " + latitude + " Longitude: " +
                longitude);
    });
Shaon
  • 2,496
  • 26
  • 27
  • How do I use this method inside a class (here the MainActivity) when the location is fetched in another class (in the GPSClass)? – user9155899 Aug 19 '18 at 12:11
  • Use this method anywhere. You can use it onResume method. It will best. Before calling the method make sure you implemented the runtime permission. – Shaon Aug 19 '18 at 12:14
  • Okay, thank you. I'm actually not familiar with Kotlin, so can you tell me what I have to add to my GPS class so I can call the function in my activity? – user9155899 Aug 19 '18 at 12:56
  • This is a util class. Just copy paste it. Fuction that I added here, call it from your onrResume function. – Shaon Aug 21 '18 at 15:26
  • Okay thank you, I will try it! is there a difference in adding a normal class or a util class? – user9155899 Aug 23 '18 at 19:03
  • No differenc. Util class is ur custom normal class. I just called that util class – Shaon Aug 24 '18 at 17:31
0

Try this this will not give you null current location

class GetLastLocation extends TimerTask {

LocationManager mlocManager = (LocationManager) 
        getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListenerTmp = new CustomLocationListener();
private final Handler mLocHandler;

public GetLastLocation(Handler mLocHandler) {
    this.mLocHandler = mLocHandler;
}

@Override
public void run() {
    timer.cancel();
    mlocManager.removeUpdates(mlocListenerTmp);
    Location location = mlocManager
            .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
    {
        if (mlocListenerTmp != null) {
            mlocManager.removeUpdates(mlocListenerTmp);
        }
        currentLocation = location;
    }
    if (location != null) {
        String message = String.format(
            "Location \n Longitude: %1$s \n Latitude: %2$s",
            location.getLongitude(), location.getLatitude());
        Log.d("loc", " :" + message);
        Bundle b = new Bundle();
        {
            b.putBoolean("locationRetrieved", true);
            {
                Message msg = Message.obtain();
                {
                    msg.setData(b);
                    mLocHandler.sendMessage(msg);
                }
            }
        }
    } else {
        Log.d(
            "loc",
            ":No GPS or network signal please fill the location manually!");
        location = mlocManager
                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (location != null) {
            currentLocation = location;
            Bundle b = new Bundle();
            {
                b.putBoolean("locationRetrieved", true);
                {
                    Message msg = Message.obtain();
                    {
                        msg.setData(b);
                        mLocHandler.sendMessage(msg);
                    }
                }
            }
        } else {
            Bundle b = new Bundle();
            {
                b.putBoolean("locationRetrieved", false);
                {
                    Message msg = Message.obtain();
                    {
                        msg.setData(b);
                        mLocHandler.sendMessage(msg);
                    }
                }
            }
        }
    }
  }
}

call it like this in your MainActivity

timer.schedule(new GetLastLocation(mLocHandler), 3000);

and the customLocationclass is as follows:

public class CustomLocationListener implements LocationListener {

@Override
public void onLocationChanged(Location loc) {
    loc.getLatitude();
    loc.getLongitude();
    currentLocation = loc;
    String Text = "My current location is: " + "Latitud = "
        + loc.getLatitude() + "Longitud = " + loc.getLongitude();
    Log.d("loc", "onLocationChanged" + Text);
}

@Override
public void onProviderDisabled(String provider) {}

@Override
public void onProviderEnabled(String provider) {}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
amit
  • 709
  • 6
  • 17
  • Thank you, that's helpful! Do you think of having `class GetLastLocation` as an nested class or a spereate class? – user9155899 Aug 19 '18 at 16:40
  • I thought so, but after a few variants of trying I still have some compilation errors. I made a different class for the CustomLocationListener and the GetLastLocation class. I did all missing declarations and now in the MainActivity call `timer.schedule(new GetLastLocation(mLocHandler), 3000);` it says that the symbol cannot be resolved. Can you tell me what to do about it? How do I initialize it in the MainActivity as well? – user9155899 Aug 19 '18 at 18:42
  • just before the line of error add `Timer timer = new Timer();` – amit Aug 20 '18 at 09:24
  • My apologies, I meant I have that issue of not being able to resolve `mLocHandler`, not the timer! – user9155899 Aug 20 '18 at 11:39
  • have you added the `GetLastLocation` Activity in the `AndroidManifest.xml` of your project? – amit Aug 20 '18 at 13:51
  • replace the error line with this `timer.schedule(new GetLastLocation(), 3000);`... hope it works.. – amit Aug 20 '18 at 14:00
  • It can't be added, it says it `is not assignable to 'android.app.Activity` and it wouldn't have a default constructor, too. Do you think it would be necessary to add it? – user9155899 Aug 20 '18 at 14:05
  • its not neccessary... replace the `class GetLastLocation extends TimerTask {` line to `public class GetLastLocation extends TimerTask {` in the `GetLastLocation` class – amit Aug 20 '18 at 14:37
  • I already did that, it didn't do the trick unfortunately. It still says `Cannot resolve symbol 'mLocHandler` – user9155899 Aug 20 '18 at 15:36
  • try putting the entire `GetLastLocation` class into your `MainActivity` ... this will work.. surely... – amit Aug 20 '18 at 16:45
  • That was my first question referring to, whether it should be a nested or a seperate class, so I already tried it. Even as a nested class I have the same error – user9155899 Aug 20 '18 at 17:08