我正在编写一个需要用户当前位置的应用程序(lastknownlocation不会非常有帮助),并显示从数据库中获取的所有最近“项目”的列表。
我发现最近的项目运作良好,但暂时仅使用硬编码的纬度和经度位置,但现在是时候实现查找实际位置了。
任何人都可以举例说明如何让应用在后台找到当前的好位置并让应用等待。当人们移动时,我只需要一次不更新的位置。我已经实现了一个位置监听器,但我知道获得GPS定位可能会很慢。我已经看到了使用上一个已知位置或实现位置监听器的其他示例,该位置监听器继续运行和更新,但是因为我的Activity需要位置坐标才能显示应用程序崩溃的任何内容。我需要在搜索时显示进度对话框。
如何让locationlistener在后台运行一次,然后在找到位置后删除位置更新。我需要应用程序的其余部分等到它有GPS位置或超时后说20-30秒。我想要一个ProgressDialog,所以用户知道某些事情正在发生,但它必须是旋转加载动画而不是百分比或任何东西。如果可能的话,我希望用户能够取消对话,如果他们厌倦了等待,那么他们可以通过键入郊区等来搜索。
我一直试图用线程来做这件事,但它变得比我觉得应该更复杂,但仍然无法工作。在iPhone上这更简单了吗?
任何人都可以提供一个很好的方法来做这件事,我已经把我的头发撕掉了一个星期,这真的让我落后于应用程序完成日期的剩余时间。
总之,我想:
*找到当前坐标
*获取位置时显示进度对话框
*应用程序能够等待成功的位置或在一定时间后放弃吗?
*如果成功:关闭进度对话框并使用坐标运行我的其他方法来查找附近的项目
*如果获取位置失败:取消进度对话框并显示错误消息,并鼓励用户使用菜单进入搜索活动。
*如果用户从菜单中选择地图视图,则使用这些坐标,以显示地图上的当前位置,并使用数据库中的坐标将所有附近项目的针脚放下。
谢谢你们,我希望我已经解释得很好了。如有任何问题,我会定期回来查看,因为我很想完成这部分。 干杯
修改
代码要求
locationList活动文件
protected void onStart()
{
super.onStart();
// ....
new LocationControl().execute(this);
}
private class LocationControl extends AsyncTask<Context, Void, Void>
{
private final ProgressDialog dialog = new ProgressDialog(branchAtmList.this);
protected void onPreExecute()
{
this.dialog.setMessage("Determining your location...");
this.dialog.show();
}
protected Void doInBackground(Context... params)
{
LocationHelper location = new LocationHelper();
location.getLocation(params[0], locationResult);
return null;
}
protected void onPostExecute(final Void unused)
{
if(this.dialog.isShowing())
{
this.dialog.dismiss();
}
useLocation(); //does the stuff that requires current location
}
}
public LocationResult locationResult = new LocationResult()
{
@Override
public void gotLocation(final Location location)
{
currentLocation = location;
}
};
LocationHelper class
package org.xxx.xxx.utils;
import java.util.Timer;
/*
imports
*/
public class LocationHelper
{
LocationManager locationManager;
private LocationResult locationResult;
boolean gpsEnabled = false;
boolean networkEnabled = false;
public boolean getLocation(Context context, LocationResult result)
{
locationResult = result;
if(locationManager == null)
{
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
}
//exceptions thrown if provider not enabled
try
{
gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
catch (Exception ex) {}
try
{
networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
catch (Exception ex) {}
//dont start listeners if no provider is enabled
if(!gpsEnabled && !networkEnabled)
{
return false;
}
if(gpsEnabled)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
}
if(networkEnabled)
{
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
}
GetLastLocation();
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location)
{
locationResult.gotLocation(location);
locationManager.removeUpdates(this);
locationManager.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extra) {}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location)
{
locationResult.gotLocation(location);
locationManager.removeUpdates(this);
locationManager.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extra) {}
};
private void GetLastLocation()
{
locationManager.removeUpdates(locationListenerGps);
locationManager.removeUpdates(locationListenerNetwork);
Location gpsLocation = null;
Location networkLocation = null;
if(gpsEnabled)
{
gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
if(networkEnabled)
{
networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
//if there are both values use the latest one
if(gpsLocation != null && networkLocation != null)
{
if(gpsLocation.getTime() > networkLocation.getTime())
{
locationResult.gotLocation(gpsLocation);
}
else
{
locationResult.gotLocation(networkLocation);
}
return;
}
if(gpsLocation != null)
{
locationResult.gotLocation(gpsLocation);
return;
}
if(networkLocation != null)
{
locationResult.gotLocation(networkLocation);
return;
}
locationResult.gotLocation(null);
}
public static abstract class LocationResult
{
public abstract void gotLocation(Location location);
}
}
为了获得当前位置,这真的是一件很大的努力吗?我不需要更新或任何其他内容?是否有更简单的方法让应用程序等待结果?我已经坚持了这么久。
答案 0 :(得分:16)
使用 AsyncTask 并使用 network_provider以及gps_provider ,这意味着两个侦听器。 gps需要更长时间才能获得修复,有时可能只需要一分钟,只能在户外工作,而网络可以快速获得位置。
这里有一个很好的代码示例:What is the simplest and most robust way to get the user's current location on Android?
对于AsyncTask,请查看http://developer.android.com/reference/android/os/AsyncTask.html
此处还有许多代码示例,例如: Android Show a dialog until a thread is done and then continue with the program
编辑: 代码概念:
添加类变量
boolean hasLocation = false;
调用onCreate(不在AsyncTask中):
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
然后在locationListener.onLocationChanged中,找到位置后更改值:
boolean hasLocation = false;
的AsyncTask: 保持原样,但不要打电话
LocationHelper location = new LocationHelper();
location.getLocation(params[0], locationResult);
那里,而不是
Long t = Calendar.getInstance().getTimeInMillies();
while (!hasLocation && Calendar.getInstance().getTimeInMillies()-t<30000)) {
Thread.Sleep(1000);
};
可能延迟介于两者之间就足够了。
答案 1 :(得分:12)
我仍然不喜欢它是如何工作的,它似乎比它应该更复杂但是直到某人提供了一种更好的方式我现在才能使用它...
如果有人遇到此情况并提出更好的清洁结果,只需获取用户当前的位置坐标,那么请停止查看,我们将非常感激!!
private LocationControl locationControlTask;
private boolean hasLocation = false;
LocationHelper locHelper;
从onCreate()我打电话
locHelper = new LocationHelper();
locHelper.getLocation(context, locationResult);
locationControlTask = new LocationControl();
locationControlTask.execute(this);
然后我有一个私人类LocationControl
private class LocationControl extends AsyncTask<Context, Void, Void>
{
private final ProgressDialog dialog = new ProgressDialog(activityname.this);
protected void onPreExecute()
{
this.dialog.setMessage("Searching");
this.dialog.show();
}
protected Void doInBackground(Context... params)
{
//Wait 10 seconds to see if we can get a location from either network or GPS, otherwise stop
Long t = Calendar.getInstance().getTimeInMillis();
while (!hasLocation && Calendar.getInstance().getTimeInMillis() - t < 15000) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
return null;
}
protected void onPostExecute(final Void unused)
{
if(this.dialog.isShowing())
{
this.dialog.dismiss();
}
if (currentLocation != null)
{
useLocation();
}
else
{
//Couldn't find location, do something like show an alert dialog
}
}
}
然后是locationResult ..
public LocationResult locationResult = new LocationResult()
{
@Override
public void gotLocation(final Location location)
{
currentLocation = new Location(location);
hasLocation = true;
}
};
另外,为了避免像我多年来一样拔出头发,请记得如果有人提前离开活动,请停止位置控制任务,并停止位置更新,以便在用户离开时停止GPS运行。在onStop()中执行以下操作:
locHelper.stopLocationUpdates();
locationControlTask.cancel(true);
Location Helper类中的stopLocationUpdates还执行以下操作:
public void stopLocationUpdates()
{
locationManager.removeUpdates(locationListenerGps);
locationManager.removeUpdates(locationListenerNetwork);
}
祝你好运,我需要它......
答案 2 :(得分:0)
为什么不在public void gotLocation(final Location location){}
上创建ProgressDialog框并将其关闭,而不是创建AsyncTask?您还可以将onCancelListener添加到ProgressDialog框并取消任何当前位置请求。