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.
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);
}
}