Android 查找 GPS 位置一次,显示加载对话框
我正在编写一个应用程序,它需要用户的当前位置(lastknownlocation 不会很有帮助)并显示从数据库中获取的所有最接近的“项目”的列表。
我已经找到了最近的项目,效果很好,但暂时只使用硬编码的纬度和经度位置,但现在是时候实现查找实际位置了。
任何人都可以提供一个示例,说明如何让应用程序在后台找到当前的精确位置并让应用程序等待。我只需要一次位置,不会随着人的移动而更新。我已经实现了一个位置侦听器,但我知道获取 GPS 修复可能会很慢。我见过其他使用最后已知位置或实现继续运行和更新的位置侦听器的示例,但是因为我的 Activity 需要位置坐标才能显示任何应用程序崩溃的内容。我需要在搜索时显示一个进度对话框。
如何让位置侦听器在后台运行一次,然后在找到位置后删除位置更新。我需要应用程序的其余部分等待,直到它有 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 类
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);
}
}
这看起来确实需要付出很大的努力才能获取当前位置一次?我不需要更新什么的?难道没有更简单的方法让应用程序等待结果吗?我已经被这个问题困扰了很长时间了。
I am writing an app that requires the user's current location (lastknownlocation won't be very helpful) and displays a list of all the closest "items" to them taken from the database.
I have got the finding of the closest items working well but only using a hardcoded latitude and longitude location for the time being but now it is time to implement finding the actual location.
Can anyone provide an example of how to have the app find the current fine location in the background and have the app wait. I only need the location once not updates as the person moves. I have implemented a location listener however I understand getting a GPS fix can be slow. I have seen other examples using last known location or implementing the location listener which continues to run and update however as my Activity needs the location coordinates before it can display anything the app just crashes. I need to show a Progress Dialog while its searching.
How can I have the locationlistener run once in the background and then remove location updates once it finds the location. I need the rest of the application to wait until it has a GPS location or timeout after say 20-30seconds. I would like a ProgressDialog up so the user knows that something is going on, but it just has to be the spinning loading animation not a percentage or anything. If possible I would like the user to be able to cancel the dialog if they are sick of waiting which then they can search by typing suburb etc instead.
I have been trying to do it with threads but it is getting way more complicated than I feel it should be and still not working anyway. On iPhone this is much more simple?
Can anyone provide a nice way of doing this, I have been ripping my hair out for a week on this and it is really putting me behind schedule for the rest of the app completion date.
In summary I want to:
* Find current coordinates
* Show Progress Dialog while getting location
* Have app be able to wait for successful location or give up after a certain time?
* If Successful: Dismiss Progress Dialog and use coordinates to run my other methods for finding items closeby.
* If Failed to get location: Dismiss Progress Dialog and show error message, and encourage user to use menu to go to Search Activity.
* Use these coordinates if the user chooses map view from the menu, to show current location on the map and pins dropped at all the nearby items by using their coordinates from the database.
Thanks guys, I hope I have explained myself well enough. Any questions just ask, I will be checking back regularly as I am keen to get this part completed.
Cheers
EDIT
Code as requested
locationList activity file
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);
}
}
This really seems like a big effort just to get the current location once? I do not require updates or anything? Is there not a simpler way of having the application wait for a result? I have been stuck on this for so long.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用AsyncTask并使用同时使用network_provider和gps_provider,这意味着两个监听器。 GPS 需要更长的时间才能修复,有时可能需要一分钟,并且只能在户外使用,而网络获取位置的速度相当快。
一个很好的代码示例在这里: 在 Android 上获取用户当前位置的最简单、最可靠的方法是什么?
对于 AsyncTask,请查看 http://developer.android.com/reference/android/os/AsyncTask.html
这里还有很多代码示例对于它,例如这里:
Android 显示一个对话框,直到线程完成,然后继续程序
编辑:
代码概念:
在onCreate中添加类变量
调用(而不是在AsyncTask中):
然后在locationListener.onLocationChanged中,一旦找到位置就更改值:
AsyncTask:
保持原样,但不要
在那里打电话,而是
在中间稍加延迟就足够了。
Use an AsyncTask and use both network_provider as well as gps_provider, which means two listeners. gps takes longer to get a fix, maybe sometimes a minute and only works outdoors, while network gets a location pretty fast.
A good code example is here: What is the simplest and most robust way to get the user's current location on Android?
For AsyncTask, look http://developer.android.com/reference/android/os/AsyncTask.html
There are also many code example here on SO for it, for example here:
Android Show a dialog until a thread is done and then continue with the program
EDIT:
code concept:
add class variable
call in onCreate (not in AsyncTask):
then in locationListener.onLocationChanged, change the value once a location is found:
AsyncTask:
leave as it is, but don't call
there, instead do
probably with a delay in between would be sufficient.
我仍然不喜欢它的工作原理,而且它看起来比应有的要复杂得多,但在有人提供更好的方法之前,我现在就让它工作......
如果有人遇到这个问题并提出更好的建议更干净的结果只需获取用户当前的位置坐标一次,然后停止查找,这将不胜感激!!
从onCreate()我调用
我然后有一个私有类LocationControl
然后是一个locationResult..
也避免你拉你的就像我多年来所做的那样,记住如果有人提前离开活动,请停止位置控制任务,并在用户离开时停止位置更新以阻止 GPS 运行。在 onStop() 中执行如下操作:
Location Helper 类中的 stopLocationUpdates 执行以下操作:
祝你好运,我需要它...
I still don't like how this works at all and it seems way more complicated than it should be but until someone provides a better way I have it working for now...
If someone comes across this and suggest a much better cleaner result to just get the user's current location coordinates just once then stop looking that would be greatly appreciated!!
From onCreate() I call
I then have a a private class LocationControl
Then a locationResult..
Also to avoid you pulling your hair out like I did for ages remember to stop the locationcontrol task if someone leaves the activity early and also stop location updates to stop the GPS from running when the user leaves. In onStop() do something like this:
Also stopLocationUpdates in the Location Helper class does the following:
Good luck with it, I needed it...
您为什么不创建一个 ProgressDialog 框并在
public void gotLocation(final Location location){}
上关闭它,而不是创建 AsyncTask?您还可以将 onCancelListener 添加到 ProgressDialog 框中并取消任何当前位置请求。Instead of creating an AsyncTask why didn't you create a ProgressDialog box and dismiss it on
public void gotLocation(final Location location){}
? You can also add a onCancelListener to the ProgressDialog box and cancel any current location requests.