在启动画面期间获取用户的地理位置
Posted
技术标签:
【中文标题】在启动画面期间获取用户的地理位置【英文标题】:Fetching geo location of a user during splashscreen 【发布时间】:2013-05-02 08:40:09 【问题描述】:我正在尝试在应用启动时(即在启动画面期间)获取用户的地理位置。
我的方法是在主要活动中使用 asynctask 从单独的类中获取地理位置。我是android新手,所以我可能会错过一些东西。这是我为获取用户地理位置而编写的示例代码:
SplashScreenActivity.java(在没有意图服务的情况下获取地理位置)
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);
当我在手机上安装此 apk 时,出现此错误:原因:java.lang.RuntimeException:无法在未调用 Looper.prepare() 的线程内创建处理程序(在后台时位于 SplashScreenActivity.java线程我尝试获取位置)
This question 也提到了错误,但在我的上下文中我无法链接它。可能是因为我在后台线程中使用了 SplashScreenActivity 上下文。但是如何纠正呢?此外,在启动画面期间查找地理位置的最佳方法是什么?请帮忙。
【问题讨论】:
【参考方案1】:你做得太过分了。在这种情况下,AsyncTask 不会完成任何事情。这是简化但仍异步获取位置的代码:
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);
【讨论】:
我还没有尝试过这种方法。但出于好奇,我也使用网络作为提供者之一。因此,如果一个人没有打开他的 GPS 但连接到 wi-fi,在这种情况下,主活动线程将调用网络操作,现在不允许这样做(应用程序将因主 Activity 上的网络原因而崩溃线)。我为此编写了 asynctask。 通常您使用 LocationManager.requestLocationUpdates() 方法设置 LocationListener。它会异步为您提供位置更新。以上是关于在启动画面期间获取用户的地理位置的主要内容,如果未能解决你的问题,请参考以下文章
Worklight Cordova 应用程序启动画面在应用程序启动期间旋转