1

I'm trying to fetch geo location of the user when the app launches, i.e, during splash screen.

My approach is to get Geo location from a separate class using asynctask in main activity. I'm new to android, so I may be missing out on something. Here is the sample code which I have written to fetch user's geo location:

SplashScreenActivity.java (fetching geo location without intent-service)

    package work.office;

import work.office.GeoLocationFinder.LocationResult;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;

public class SplashScreenActivity extends Activity {

    private static final String TAG = "SplashScreenActivity";
    private ProgressDialog pd = null;
    private Object data = null;
    LocationResult locationResult;
    Location newLocation = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);

        new GetGeoLocationAsyncTask(getApplicationContext()).execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.splash_screen, menu);
        return true;
    }

    private class GetGeoLocationAsyncTask extends
            AsyncTask<Void, Integer, Location> {

        private static final String TAG = "GetGeoLocationAsyncTask";
        private Context ctx = null;

        public GetGeoLocationAsyncTask(Context applicationContext) {
            this.ctx = applicationContext;
        }

        @Override
        protected void onPreExecute() {
            pd = new ProgressDialog(SplashScreenActivity.this);
            pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pd.setTitle("Loading...");
            pd.setMessage("Finding your geo location... Please wait");
            pd.setCancelable(Boolean.FALSE);
            pd.setIndeterminate(Boolean.TRUE);
            pd.setMax(100);
            pd.setProgress(0);
            pd.show();
            super.onPreExecute();
        }

        @Override
        protected Location doInBackground(Void... params) {

                    LocationResult locationResult = new LocationResult() {

                        @Override
                        public void gotLocation(Location location) {
                            if (location != null) {

                                newLocation = new Location(location);
                                newLocation.set(location);
                            } else {
                                Log.d(TAG, "Location received is null");
                            }

                        }

                    };
                    GeoLocationFinder geoLocationFinder = new GeoLocationFinder();
                    geoLocationFinder.getLocation(this.ctx,
                            locationResult);

            return newLocation;
        }

        @Override
        protected void onPostExecute(Location result) {
            super.onPostExecute(result);
            if (result != null) {
                Log.d(TAG,
                        "Got coordinates, congratulations. Longitude = "
                                + result.getLongitude() + " Latitude = "
                                + result.getLatitude());
            } else {
                Log.d(TAG, "Coordinates are null :(");
            }
            pd.dismiss();
        }

    }

}

GeoLocationFinder.java

   package work.office;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;

public class GeoLocationFinder {
    private static final String TAG = "GeoLocationFinder";
    Timer locationTimer;
    LocationManager locationManager;
    Location location;
    private static final int min_update_time = 20000; // in msec
    private static final int min_distance_for_update = 10; // in meters
    LocationResult locationResult;
    boolean gps_enabled = Boolean.FALSE;
    boolean network_enabled = Boolean.FALSE;

    public boolean getLocation(Context ctx, LocationResult result) {
        locationResult = result;

        if (locationManager == null) {
            locationManager = (LocationManager) ctx
                    .getSystemService(Context.LOCATION_SERVICE);
        }

        try {
            gps_enabled = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);
        } catch (Exception e) {
            Log.d(TAG, "GPS enabled exception: " + e.getMessage());
        }

        try {
            network_enabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch (Exception e) {
            Log.d(TAG, "Network enabled exception: " + e.getMessage());
        }

        if (!gps_enabled && !network_enabled) {
            Log.d(TAG, "You are doomed boy!!");
            return Boolean.FALSE;
        }

        if (gps_enabled) {
            locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, min_update_time,
                    min_distance_for_update, locationListenerGps);
        }

        if (network_enabled) {
            locationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, min_update_time,
                    min_distance_for_update, locationListenerNetwork);
        }

        locationTimer = new Timer();
        locationTimer.schedule(new GetLastLocation(), 20000);
        return Boolean.TRUE;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            locationTimer.cancel();
            locationResult.gotLocation(location);
            locationManager.removeUpdates(this);
            locationManager.removeUpdates(locationListenerGps);
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.d(TAG, "GPS provider disabled" + provider);

        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.d(TAG, "GPS provider enabled" + provider);

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.d(TAG, "GPS status changed");

        }


    };

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {
            locationTimer.cancel();
            locationResult.gotLocation(location);
            locationManager.removeUpdates(this);
            locationManager.removeUpdates(locationListenerNetwork);
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.d(TAG, "Network provider disabled. " + provider);

        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.d(TAG, "Network provider enabled. " + provider);

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.d(TAG, "Network status changed.");

        }
    };

    private class GetLastLocation extends TimerTask {

        @Override
        public void run() {
            locationManager.removeUpdates(locationListenerGps);
            locationManager.removeUpdates(locationListenerNetwork);
            Location net_loc = null, gps_loc = null;
            if (gps_enabled) {
                gps_loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            }
            if (network_enabled) {
                net_loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }
            if (gps_loc != null && net_loc != null) {
                if (gps_loc.getTime() > net_loc.getTime()) {
                    locationResult.gotLocation(gps_loc);
                } else {
                    locationResult.gotLocation(net_loc);
                }
                return;
            }

            if (gps_loc != null) {
                locationResult.gotLocation(gps_loc);
                return;
            }

            if (net_loc != null) {
                locationResult.gotLocation(net_loc);
                return;
            }

            locationResult.gotLocation(null);

        }

    }

    public static abstract class LocationResult {
        public abstract void gotLocation(Location location);
    }
}

When i install this apk on my phone, I get this error: Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() (in SplashScreenActivity.java when in background thread I try to get location)

This question also mentions of the error but in my context I'm not able to link it. Could be because I have used SplashScreenActivity context in background thread. But how to rectify it? Also, what could be the best approach to find geo location during splash screen? Please help.

Community
  • 1
  • 1
Ankit Garg
  • 709
  • 1
  • 11
  • 26

1 Answers1

2

You are seriously overdoing it. The AsyncTask does not accomplish anything in this case. Here is the code simplified but still asynchronously getting the location:

package work.office;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;

public class SplashScreenActivity extends Activity {

    private static final String TAG = "SplashScreenActivity";
    private ProgressDialog pd = null;
    private Object data = null;
    GeoLocationFinder.LocationResult locationResult;
    Location newLocation = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);

        setupLocation();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.splash_screen, menu);
        return true;
    }

    private void setupLocation() {
        pd = new ProgressDialog(SplashScreenActivity.this);
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pd.setTitle("Loading...");
        pd.setMessage("Finding your geo location... Please wait");
        pd.setCancelable(Boolean.FALSE);
        pd.setIndeterminate(Boolean.TRUE);
        pd.setMax(100);
        pd.setProgress(0);
        pd.show();

        GeoLocationFinder.LocationResult locationResult = new GeoLocationFinder.LocationResult() {

            @Override
            public void gotLocation(Location location) {
                if (location != null) {

                    newLocation = new Location(location);
                    newLocation.set(location);

                    Log.d(TAG,
                            "Got coordinates, congratulations. Longitude = "
                                    + newLocation.getLongitude() + " Latitude = "
                                    + newLocation.getLatitude());
                    pd.dismiss();
                } else {
                    Log.d(TAG, "Location received is null");
                }

            }

        };
        GeoLocationFinder geoLocationFinder = new GeoLocationFinder();
        geoLocationFinder.getLocation(this,
                locationResult);
    }
}
Damodaran
  • 10,882
  • 10
  • 60
  • 81
mach
  • 8,315
  • 3
  • 33
  • 51
  • I haven't tried this approach yet. But out of curiousity, I'm using network also as one of the provider. So if a person hasn't turned his GPS on but is connected to wi-fi, in this case, the main activity thread will be calling a network operation, which is now not permitted (the application will crash with reason Network on main Activity thread). I wrote asynctask for that purpose. – Ankit Garg May 09 '13 at 11:48
  • Normally you set a LocationListener using LocationManager.requestLocationUpdates()-method. It will give you location updates asynchronously. – mach May 10 '13 at 07:38