从不调用 OnLocationChanged 回调

我试图得到用户当前的位置使用 LocationManager。我做了很多研究,似乎找不到有同样问题的人。OnLocationChanged回调函数似乎从未被调用过。下面是我的各种代码和 logcat。

protected LocationListener locationListener;
protected LocationManager locationManager;
protected Context context;

我的 OnCreate()方法

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG, "IN ON CREATE");


this.context = getActivity();


registerLocationUpdates();
}

我的 registerLocationUpdates方法

void registerLocationUpdates() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_LOW);
criteria.setPowerRequirement(Criteria.POWER_LOW);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);


locationManager = (LocationManager)getActivity().getSystemService(LOCATION_SERVICE);


provider = locationManager.getBestProvider(criteria, true);


// Cant get a hold of provider
if (provider == null) {
Log.v(TAG, "Provider is null");
showNoProvider();
return;
} else {
Log.v(TAG, "Provider: " + provider);
}


locationListener = new MyLocationListener();


locationManager.requestLocationUpdates(provider, 1L, 1f, locationListener);


// connect to the GPS location service
Location oldLocation = locationManager.getLastKnownLocation(provider);


if (oldLocation != null)  {
Log.v(TAG, "Got Old location");
latitude = Double.toString(oldLocation.getLatitude());
longitude = Double.toString(oldLocation.getLongitude());
waitingForLocationUpdate = false;
getNearbyStores();
} else {
Log.v(TAG, "NO Last Location found");
}
}

我的 LocationListener

private class MyLocationListener implements LocationListener {


public void onLocationChanged(Location location) {
latitude = Double.toString(location.getLatitude());
longitude = Double.toString(location.getLongitude());


Log.v(TAG, "IN ON LOCATION CHANGE");


if (waitingForLocationUpdate) {
getNearbyStores();
waitingForLocationUpdate = false;
}


locationManager.removeUpdates(this);
}


public void onStatusChanged(String s, int i, Bundle bundle) {
Log.v(TAG, "Status changed: " + s);
}


public void onProviderEnabled(String s) {
Log.e(TAG, "PROVIDER DISABLED: " + s);
}


public void onProviderDisabled(String s) {
Log.e(TAG, "PROVIDER DISABLED: " + s);
}
}

我在 Android 清单中的权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

最后是运行应用程序后的 logcat

01-25 09:43:10.963: VERBOSE/NearbyListFragment(3060): IN ON CREATE
01-25 09:43:10.963: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.963: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.973: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.983: VERBOSE/NearbyListFragment(3060): Provider: gps
01-25 09:43:10.983: DEBUG/LocationManager(3060): requestLocationUpdates: provider = gps, listener = co.fusionweb.dealsplus.app.NearbyItems$NearbyListFragment$MyLocationListener@46ef4680
01-25 09:43:10.983: DEBUG/GpsLocationProvider(1329): setMinTime 1
01-25 09:43:10.983: VERBOSE/NearbyListFragment(3060): NO Last Location found
01-25 09:43:10.983: VERBOSE/LocationManagerService(1329): _requestLocationUpdates: listener = Receiver{47421e68 Listener android.os.BinderProxy@47421a68}
01-25 09:43:11.003: VERBOSE/countingFragment(3060): IN ON CREATE VIEW
01-25 09:43:11.003: WARN/GpsLocationProvider(1329): Duplicate add listener for co.fusionweb.dealsplus
01-25 09:43:11.013: VERBOSE/ScrollListener(3060): In Constructor
01-25 09:43:11.013: VERBOSE/ScrollListener(3060): Scrolling
01-25 09:43:11.033: DEBUG/GpsLocationProvider(1329): startNavigating
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_qos_time_out(standalone = 60, agps = 89)
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_qos_accuracy(accuracy = 50)
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): persist.radio.agps.mode: []
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_position mode, client = 1, interval = 1, mode = 1
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): loc_eng_ioctl called: client = 1, ioctl_type = 2
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): loc_ioctl
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [96]
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet size: [28]
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): loc_api_sync_ioctl: select_id = 0, loc_ioctl returned 0
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): Callback received: 80 (cb_id=0x5310000 handle=1)
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [28]
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): loc_eng_ioctl result: client = 1, ioctl_type = 2, SUCCESS
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_start
01-25 09:43:11.043: DEBUG/locapi_rpc_glue(1329): loc_start_fix
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [44]
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.053: DEBUG/RPC(1329): read RPC packet size: [28]
01-25 09:43:11.103: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.103: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.113: VERBOSE/locapi_rpc_glue(1329): Callback received: 100 (cb_id=0x5310000 handle=1)
01-25 09:43:11.113: VERBOSE/lib_locapi(1329): process_deferred_action: pthread_cond_wait returned
01-25 09:43:11.113: DEBUG/lib_locapi(1329): loc_eng_report_status: GPS_STATUS_SESSION_BEGIN
01-25 09:43:11.113: DEBUG/lib_locapi(1329): loc_eng_report_status: update status
01-25 09:43:11.113: VERBOSE/GpsLocationProvider(1329): reportStatus status: 1
01-25 09:43:11.113: DEBUG/GpsLocationProvider(1329): Acquiring wakelock
01-25 09:43:11.123: DEBUG/RPC(1329): written RPC packet size: [28]
01-25 09:43:11.183: DEBUG/PowerManagerService(1329): New lightsensor value:40, lcdValue:77
01-25 09:43:11.273: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.273: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.273: VERBOSE/locapi_rpc_glue(1329): Callback received: 100 (cb_id=0x5310000 handle=1)
01-25 09:43:11.273: VERBOSE/lib_locapi(1329): process_deferred_action: pthread_cond_wait returned
01-25 09:43:11.273: DEBUG/lib_locapi(1329): loc_eng_report_status: GPS_STATUS_ENGINE_ON
01-25 09:43:11.273: DEBUG/lib_locapi(1329): loc_eng_report_status: update status
01-25 09:43:11.273: VERBOSE/GpsLocationProvider(1329): reportStatus status: 3

Logcat 的 android SDK 定位部分不断重复它们自己。我已经尝试了一切我能想到的,并已经看到在谷歌和堆栈溢出。作为一个侧面说明,我已经能够让它工作在一个2.3设备上使用的 requestSingleUpdate,这是在 API 9和遵循指南 深入定位,但我需要它工作在2.1或2.2以上使用旧的 SDK。因此,如果你有任何提示或想知道更多,请让我知道。先谢谢你。

95120 次浏览

看起来您的设置应该可以工作,因为它不能工作,我将使您的示例尽可能简单,以便进行故障排除。我会让你的要求看起来像

requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

这样你可以得到所有可能的更新。然后把最后一个已知地点的部分删掉。现在还不需要。

然后在 onLocationChanged(),只要有

Log.v(TAG, "IN ON LOCATION CHANGE, lat=" + latitude + ", lon=" + longitude);

把剩下的说出来,这样你就能让你的听众保持活跃。这将为您提供实际设备上的更新流。在模拟器上,您将需要使用 DDMS,并且每次按发送时将获得一次 GPS 更新。

正如史蒂夫 · 布莱克威尔所写,你的设置很好。你的 可以尝试是理解,如果你100% 有一个 GPS 固定信号!我已经安装了一个不错的 GPS 测试器应用程序(来自游戏商店),它会告诉你,如果你有一个修复或没有,你连接到哪些卫星,什么是连接强度。 这就是为什么我的 OnLocationChanged ()从来没有打过电话. . 我试着在一个建筑物内运行它:

祝你好运!

我也面临同样的问题。我得到的最新位置是空的。当我重新启动设备和设备中的 Location 服务时,问题就解决了。

替换

定位管理器 GPS _ PROVIDER

网络 _ 提供者

解决了我的问题。

下面是我的位置管理器的代码片段

 LocationManager locationManager = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE);

//检查位置权限,棉花糖和以上

        if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
//    ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
//   public void onRequestPermissionsResult(int requestCode, String[] permissions,
//                                          int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.


Toast.makeText(getActivity(), "Not Enough Permission", Toast.LENGTH_SHORT).show();
return;
}

//从当前位置开始

        Location myLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);


currentLatitude = myLocation.getLatitude();
currentLongitude = myLocation.getLongitude();

//使用 LocationManager.NETWORK _ PROVIDER 请求位置更新

        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, MapFragment.this);

我也遇到过类似的问题。我有权限,请求服务正确,但没有更新来。事实证明,我所要做的就是等待。当我在互联网上搜索这个问题时,我让应用程序运行起来,几分钟后它就开始接收更新。然后,即使当我关闭应用程序并再次运行它,更新即时到来-我想这是一个系统的事情,一些优化,也许是由于事实上,设备没有移动(顺便说一下。这不是什么垃圾设备,这是像素)。

GPS 供应商 就会失效时,设备在低功耗或使用节能模式,那么在这种情况下,我们不能接收 onLocationChanged

GPS 供应商 几乎再也不回来了的位置,如果你留在家里或建筑物(只有在户外工作良好)

因此,在我的应用程序中,我将同时使用 GPS_PROVIDERNETWORK_PROVIDER来更好地接收 onLocationChanged()

Https://developer.android.com/guide/topics/location/strategies.html#updates

若要从 GPS 提供程序请求位置更新,请使用 GPS _ PROVIDER 您也可以请求位置更新 从全球定位系统和网络位置提供商通过调用 RequestLocationUpdate ()两次ーー一次用于 NETWORK _ PROVIDER,一次用于 GPS _ PROVIDER.

如果您正在尝试使用 NETWORK _ PROVIDER,那么它确实很难测试:

  • 模拟器: 从不工作
  • 在真实设备上: 只有 getLastKnownLocation ()可以工作,要接收 onLocationChanged () ,你必须使用移动数据并且冒着从 Robber 那里丢失手机的风险出去: P

我猜测原因是它只是网络提供者的位置,而不是您的设备本身,并且网络提供者从不移动,所以 onLocationChanged ()从不调用。它可能只发生在移动数据和 wifi 之间的切换,反之亦然。如果我说错了,请纠正我。

因此,我建议在考虑性能和电池使用之前,先用 GPS _ PROVIDER 进行试验。它在模拟器和实际设备上都能很好地工作。最佳实践: https://developer.android.com/guide/topics/location/strategies.html

我花了几个小时用 NETWORK _ PROVIDER 进行测试,没有任何结果,所以希望我的建议有帮助。

我在我的实际设备(M,应用程序的 targetSDK 23)上遇到了同样的问题(onLocationChanged ()从未用 NETWORK _ PROVIDER 调用过) ,直到我重新启动它。

正如 Phan Van Linh回答的那样,这可能是因为你在一座建筑物内。 有解释 给你如何为模拟器模拟 GPS。 此外,还有 这个应用程序,模拟 GPS 数据。

LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (manager != null) {
List<String> providers = manager.getAllProviders();
for (String provider : providers) {
manager.requestLocationUpdates(provider, TIME_BW_UP, DISTANCE_BW_UP, locationListener);
}
}

很抱歉碰撞了这样一个老的线程,但这可能会方便其他一些人,因为这个问题是排名相对较高的谷歌搜索。

我有一个类似的问题,onlocationchange 没有被解雇,但是我找不到我的代码有什么问题。在尝试了各种组合之后,我意识到问题的根本原因是我正在服务中注册侦听器。

该服务是一个前台服务,所以基于谷歌 文件应该工作,它没有!

将初始化包装在一个方法中,并从创建或绑定到服务的活动中调用该方法解决了我的问题。

这就是我的服务方式:

void start_gps_track(int i) {
if (myCarLocationListener!=null) {
if (i==1) //if start night
myCarLocationListener.setNightstart(true);
else if (i==2) //if start GPS
myCarLocationListener.setLocationStart(true);
return;
}
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if ( locationManager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
myCarLocationListener=new CarLocationListener(this,adjust_audio);
if (i==1) //if start night
myCarLocationListener.setNightstart(true);
else if (i==2) //if start GPS
myCarLocationListener.setLocationStart(true);
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, myCarLocationListener);
Log.d("HU","Registered location listener");
Location lastlocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (lastlocation == null)
lastlocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastlocation != null)
myCarLocationListener.onLocationChanged(lastlocation);
}
catch (SecurityException e){
Log.e("HU-GPS","No permission to access Location");
}
}
else
{
Log.e("HU-GPS","No GPS provider or no permission");
}
}

如果我从服务本身调用它,我将不会收到任何位置更新(再次注意,服务是一个 FOREGROound 服务,它实际上绑定到一个当前正在运行的活动)。

但是,如果我从创建/绑定到服务的活动中调用这个方法,它会工作得很好:

@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
TransporterService.LocalBinder binder = (TransporterService.LocalBinder) service;
mService = binder.getService();
mService.updatePlayer(player.this);
try {
mService.start_gps_track(0);
}
catch (Exception e) {            //This should only happen if there is no GPS provider available, but it might happen quickly after boot when the device is not yet ready.
mService.recheck_gps(0);
}


mBound = true;
}


@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;


}
};

希望这对其他遇到这个问题的人有所帮助。

我有两个设备: 三星Galaxy S4(Android 5.0.1)和顶点赢(Android 8.1)。

在三星一切工作正确和快速,全球定位系统坐标被发现,并称为 onLocationChanged

在优先级为 PRIORITY_BALANCED_POWER_ACCURACY的顶点上,它可能首先与网络提供商进行交互,因此它通过 Wi-Fi 找到坐标。但是它不能检测正确,定位服务是否打开(一段时间后,设备认为它是打开的,而它是关闭的,并调用 LocationServices.getSettingsClientaddOnSuccessListener方法。所以我换到 PRIORITY_HIGH_ACCURACY又得到了一个惊喜。网络供应商关闭了,但是没有调用 onLocationChanged,所以我无法得到坐标。我从 Play Market 下载了 GPS tester(@Li3ro 建议) ,看到卫星可见,但没有固定信号。我在大楼里接收不到信号。

即使是独立的地图也不能接收坐标,但户外可以。所以,在我离开之后,我可以在一个应用程序中找到我的坐标。

另见 https://stackoverflow.com/a/27828929/2914140,其中提到了优先级和错误识别(如果没有找到坐标,在一段时间后禁用 GPS)。

这应该是由于您的手机设置。在电话位置设置,如果位置服务模式设置为 GPS 只,然后 OnLocationChanged 回调电话时,有 GPS 修复。通过选择使用 GPS,WI-FI 和移动网络选项,位置将通过使用这三个供应商来确定。这将减少定位设备位置所需的时间。 * * * 访问位置服务的路径可以更改设备到设备。 谢谢

这种情况发生在我的位置被关闭的时候。不是应用程序的位置权限,而是 Android 设备本身的位置。请求用户激活 GPS 为我修复它:

protected void onCreate(Bundle savedInstanceState) {
//...
final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );


if ( !manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
buildAlertMessageNoGps();
}
}


private void buildAlertMessageNoGps() {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Your GPS seems to be disabled, do you want to enable it?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
dialog.cancel();
}
});
final AlertDialog alert = builder.create();
alert.show();
}

来自 给你的解决方案。

你可能还需要关掉 GPS,然后再打开,以触发一个对话框来提高定位精度:

Dialog prompting to improve location accuracy

在我的情况下,即使编写了正确的代码,我也没有使用 client.requestLocationUpdates(locationRequest, this, it)获得位置。 在手机 GPS 启用,以及使用

val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)

在花时间切换模拟器,构建等,最后发现位置模式是“只有设备”,它没有提供结果的模拟器。切换到“高精度”,它开始工作。

在我的情况下,GPS 被禁用了。

所以我从设置开始打开外景,它工作得很好