Android:从最佳可用提供商处获取当前位置
我有一些Android代码,需要快速从GPS、网络或任何可用的位置获取最佳可用位置。准确度不如速度重要 获得最佳可用位置肯定是一项真正的标准任务。但是我找不到任何代码来演示它。Android位置代码要求你指定标准,注册更新,然后等待——如果你有详细的标准并且不介意等待,这是很好的 但我的应用程序需要更像地图应用程序在第一次找到你时那样工作——从任何可用的提供商那里工作,只需检查位置是否完全过时或为空 我已经尝试使用自己的代码来实现这一点,但遇到了问题。(如果有什么区别的话,上传是在IntentService内部进行的。我已经包含了所有的信息代码。)这个代码有什么问题Android:从最佳可用提供商处获取当前位置,android,Android,我有一些Android代码,需要快速从GPS、网络或任何可用的位置获取最佳可用位置。准确度不如速度重要 获得最佳可用位置肯定是一项真正的标准任务。但是我找不到任何代码来演示它。Android位置代码要求你指定标准,注册更新,然后等待——如果你有详细的标准并且不介意等待,这是很好的 但我的应用程序需要更像地图应用程序在第一次找到你时那样工作——从任何可用的提供商那里工作,只需检查位置是否完全过时或为空 我已经尝试使用自己的代码来实现这一点,但遇到了问题。(如果有什么区别的话,上传是在IntentS
@Override
protected void onHandleIntent(Intent arg0) {
testProviders();
doUpload();
}
private boolean doUpload() {
int j = 0;
// check if we have accurate location data yet - wait up to 30 seconds
while (j < 30) {
if ((latString == "") || (lonString == "")) {
Log.d(LOG_TAG, "latlng null");
Thread.sleep(1000);
j++;
} else {
Log.d(LOG_TAG, "found lat " + latString + " and lon " + lonString);
break;
}
//do the upload here anyway, with or without location data
//[code removed for brevity]
}
public boolean testProviders() {
Log.e(LOG_TAG, "testProviders");
String location_context = Context.LOCATION_SERVICE;
locationmanager = (LocationManager) getSystemService(location_context);
List<String> providers = locationmanager.getProviders(true);
for (String provider : providers) {
Log.e(LOG_TAG, "registering provider " + provider);
listener = new LocationListener() {
public void onLocationChanged(Location location) {
// keep checking the location - until we have
// what we need
//if (!checkLoc(location)) {
Log.e(LOG_TAG, "onLocationChanged");
locationDetermined = checkLoc(location);
//}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
};
locationmanager.requestLocationUpdates(provider, 0,
0, listener);
}
Log.e(LOG_TAG, "getting updates");
return true;
}
private boolean checkLoc(Location location) {
float tempAccuracy = location.getAccuracy();
int locAccuracy = (int) tempAccuracy;
Log.d(LOG_TAG, "locAccuracy = " + locAccuracy);
if ((locAccuracy != 0) && (locAccuracy < LOCATION_ACCURACY)) {
latitude = location.getLatitude();
longitude = location.getLongitude();
latString = latitude.toString();
lonString = longitude.toString();
return true;
}
return false;
}
public void removeListeners() {
// Log.e(LOG_TAG, "removeListeners");
if ((locationmanager != null) && (listener != null)) {
locationmanager.removeUpdates(listener);
}
locationmanager = null;
// Log.d(LOG_TAG, "Removed " + listener.toString());
}
@Override
public void onDestroy() {
super.onDestroy();
removeListeners();
}
似乎暗示网络供应商确实有一些位置信息,毕竟,我只是不明白
有人能帮忙吗?我认为工作示例代码将是Android/StackOverflow社区的有用资源。生产代码中的Thread.sleep()是一种严重的代码气味。如果你发现你必须这样做,你可能在做一些不应该这样做的事情。在这种情况下,我认为这是你的问题的根源——你不能让Android回去处理这个线程的消息队列来发送它找到的任何位置更新。我怀疑
IntentService
对您的场景不起作用。您肯定是在努力做到这一点。下面是我正在开发的一个新应用程序的一些片段。它用于让所有提供商能够在无成本的情况下返回高精度
如果未启用任何提供程序,将显示一个对话框,提示用户打开其位置设置。如果用户点击ok,实际上会触发一个意向,将其发送到手机上的设置。如果有已启用的提供商,则应用程序将从任何已启用的提供商获取最新的。对于我的应用程序,我只需要知道用户所在的一般区域,最后一个已知位置很可能是他们的家乡
如果启用了提供程序,循环也会尽快请求位置更新。这是我的应用程序的理想选择,但您可以更改此选项以节省电池电量,并修改应用程序的参数
这段代码中的优化(Android应用程序上的示例并未真正显示)是所有启用的提供者都同时启动。所有提供程序将在上返回单独的更新。在我的应用程序中,当其中一个提供商以足够高的精度返回位置后,我删除位置侦听器
开始位置更新:
void getCurrentLocation() {
List<String> providers = locationManager.getProviders(criteria, true);
if (providers != null) {
Location newestLocation = null;
for (String provider : providers) {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
if (newestLocation == null) {
newestLocation = location;
} else {
if (location.getTime() > newestLocation.getTime()) {
newestLocation = location;
}
}
locationManager.requestLocationUpdates(provider, 0, 0, this);
}
}
} else {
LocationDialogFragment dialog = new LocationDialogFragment();
dialog.show(getSupportFragmentManager(),
LocationDialogFragment.class.getName());
}
}
谢谢我想我会在正常活动中这样做,然后将lat/lon传递给IntentService。我仍然非常喜欢一个如何检查所有LocationProviders并选择最佳位置的示例-如果有人有任何示例代码,请发布它。。。如果没有,我将尝试破解某些东西并将其发布到这里。@commonware-您建议我如何在不使用Thread.sleep()的情况下实现以下内容?“持续检查位置更新30秒;如果到那时还没有找到最新的位置,请放弃并使用虚拟值。”Thread.sleep可以用于生产代码中有无数个原因(尽管我在这里不一定要说)。也许我的代码示例可以帮到很好的解决方案!只有一件事需要指出。这可能是由于API中的更改,但是条件
(providers!=null)
必须是(privers.size()>0)
,因为getProviders(Criteria,boolean)
方法从不返回null
,相反,它可以返回一个大小为0的列表。我想我记得当我测试这个时并不准确,但我想我们必须看文档。无论如何,每个人都应该知道Google Play服务库中的FusedLocationProvider比旧的location类优越得多。但实现方式却大不相同。这项技术有点过时。你能告诉我们你是如何建立“标准”对象的。。。我还需要一个大概的位置(城市精度)
void getCurrentLocation() {
List<String> providers = locationManager.getProviders(criteria, true);
if (providers != null) {
Location newestLocation = null;
for (String provider : providers) {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
if (newestLocation == null) {
newestLocation = location;
} else {
if (location.getTime() > newestLocation.getTime()) {
newestLocation = location;
}
}
locationManager.requestLocationUpdates(provider, 0, 0, this);
}
}
} else {
LocationDialogFragment dialog = new LocationDialogFragment();
dialog.show(getSupportFragmentManager(),
LocationDialogFragment.class.getName());
}
}
@Override
public void onLocationChanged(Location location) {
float bestAccuracy = -1f;
if (location.getAccuracy() != 0.0f
&& (location.getAccuracy() < bestAccuracy) || bestAccuracy == -1f) {
if (location.getAccuracy() < Const.MIN_ACCURACY) {
locationManager.removeUpdates(this);
}
}
bestAccuracy = location.getAccuracy();
}
public class LocationDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.location_dialog_message)
.setPositiveButton(R.string.location_dialog_positive_button,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent settingsIntent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(settingsIntent);
}
})
.setNegativeButton(R.string.location_dialog_negative_button,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(),
R.string.no_location_message, Toast.LENGTH_LONG)
.show();
}
});
return builder.create();
}
}