我正在尝试使用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);
}
}
我在AndroidManifest中的权限
<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位置部分不断重复它们。我已经尝试了一些我能想到并在google和stackoverflow上看到过的东西。 Als只是作为附注,我已经能够使用API 9中提供的requestSingleUpdate
并遵循指南A Deep Dive into Location使其在2.3设备上工作但我需要它在2.1上工作使用旧的SDK或2.2及更高版本。如果您有任何提示或想了解更多,请告诉我。提前谢谢。
答案 0 :(得分:57)
看起来你的设置应该可行,因为它没有,我会让你的例子尽可能简单,以便排除故障。我会让你的请求看起来像
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更新。
答案 1 :(得分:10)
更换
LocationManager.GPS_PROVIDER
与
LocationManager.NETWORK_PROVIDER
解决了我的问题。
以下是我的位置管理员的代码段
var pageViewController: UIPageViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
self.pageViewController = UIPageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal, options: nil)
self.pageViewController!.delegate = self
let startingViewController: DataViewController = self.modelController.viewControllerAtIndex(0, storyboard: self.storyboard!)!
let viewControllers = [startingViewController]
self.pageViewController!.setViewControllers(viewControllers, direction: .forward, animated: false, completion: {done in })
self.pageViewController!.dataSource = self.modelController
self.addChildViewController(self.pageViewController!)
self.view.addSubview(self.pageViewController!.view)
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
var pageViewRect = self.view.bounds
if UIDevice.current.userInterfaceIdiom == .pad {
pageViewRect = pageViewRect.insetBy(dx: 40.0, dy: 40.0)
}
self.pageViewController!.view.frame = pageViewRect
self.pageViewController!.didMove(toParentViewController: self)
}
//检查位置权限,Marshmallow及以上
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;
}
//使用LocationManager.NETWORK_PROVIDER
请求位置更新 Location myLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
currentLatitude = myLocation.getLatitude();
currentLongitude = myLocation.getLongitude();
答案 2 :(得分:7)
onLocationChanged
如果您呆在房屋或建筑物内(仅在户外工作良好),GPS提供商几乎不会返回
因此,在我的应用中,我会同时使用GPS_PROVIDER
和NETWORK_PROVIDER
来更好地接收onLocationChanged()
https://developer.android.com/guide/topics/location/strategies.html#Updates
要从GPS提供商处请求位置更新,请使用GPS_PROVIDER 而不是NETWORK_PROVIDER。您还可以请求位置更新 通过呼叫从GPS和网络位置提供商 requestLocationUpdates()两次 - 一次用于NETWORK_PROVIDER,一次用于 GPS_PROVIDER。
答案 3 :(得分:4)
史蒂夫布莱克威尔写道,你的设置很好。您可以尝试的是了解您是否100%拥有GPS固定信号!我已经安装了一个不错的GPS Tester application (from the play store),它会告诉你是否有修复,以及你连接的卫星和连接强度是多少。 这就是我的OnLocationChanged()永远不会调用的原因..我尝试在建筑物内运行它:\
祝你好运!答案 4 :(得分:1)
我遇到了类似的问题。我有权限,请求正确服务,但没有更新。事实证明,我所要做的只是等待。当我在互联网上搜索问题时,我运行了应用程序,几分钟后它才开始接收更新。然后,即使我杀了应用程序并再次运行它,更新即时发生 - 我想这是一个系统的事情,一些优化,可能是因为设备根本没有移动(顺便说一下。它不是一些糟糕的设备,它是Pixel)。
答案 5 :(得分:1)
我有相同的情况,我以为我在我的代码中犯了一些错误所以onlocationchage方法没有被调用,最后我像这样解决了。
Step 1 :
Close your application and Open Google Map Application.
Step 2 :
Touch the location finder button or icon over the Google Map app then It will show, currently where you are located.
Step 3 :
Now Run your app and check onlocationchage will call.
答案 6 :(得分:0)
我遇到了同样的问题。我的getLastKnownLocation为null。当我在设备中重新启动设备和位置服务时,问题得以解决。
答案 7 :(得分:0)
如果您尝试使用NETWORK_PROVIDER,则很难进行测试:
我想原因是它只是网络提供商的位置而不是你的设备本身,而网络提供商从不移动,所以onLocationChanged()从不调用。它可能仅在移动数据和wifi之间切换时发生,反之亦然。如果我错了,请纠正我。
所以我建议在考虑性能和电池使用情况之前使用GPS_PROVIDER进行实验。它在仿真器和真实设备上都能很好地工作。最佳做法:https://developer.android.com/guide/topics/location/strategies.html
使用NETWORK_PROVIDER进行测试花了几个小时没有任何结果,所以希望我的建议很有帮助。
答案 8 :(得分:0)
我在我的真实设备(M,应用程序的targetSDK 23)上遇到了同样的问题(onLocationChanged()从未使用NETWORK_PROVIDER调用),直到我重新启动它。
答案 9 :(得分:0)
答案 10 :(得分:0)
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);
}
}
答案 11 :(得分:0)
很抱歉碰到这样一个老话题,但这可能对其他人来说很方便,因为这个问题在Google搜索中的排名相对较高。
我有一个类似的问题,onlocationchanged没有被解雇,但是我的代码找不到任何错误。在尝试了各种组合之后,我意识到问题的根本原因是我在服务中注册了侦听器。
该服务是一项前台服务,因此基于应该工作的Google documentation,它没有作用!
在方法中包装初始化,然后从创建或绑定到服务的活动中调用该方法解决了我的问题。
这是我提供服务的方法:
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");
}
}
如果我从服务本身内部调用它,我将不会收到任何位置更新信息(再次注意,该服务是一项FOREGROUND服务,它实际上已绑定到当前正在运行的活动)。
但是,如果我从创建/绑定到该服务的活动中调用此方法,如下所示,它就可以正常工作:
@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;
}
};
希望这对遇到此问题的其他人有所帮助。
答案 12 :(得分:0)
我有2台设备:Samsung Galaxy S4(Android 5.0.1)和Vertex Win(Android 8.1)。
在Samsung上,一切正常且快速,可以找到GPS坐标,并调用onLocationChanged
。
在顶点PRIORITY_BALANCED_POWER_ACCURACY
中的顶点上,它可能首先与网络提供商进行交互,因此它通过Wi-Fi查找坐标。但是它无法检测到是否打开了定位服务(在一段时间后设备认为它已打开,而关闭时又调用了addOnSuccessListener
的{{1}}方法。因此,我切换到LocationServices.getSettingsClient
并带来另一个惊喜。网络提供商已关闭,但未致电PRIORITY_HIGH_ACCURACY
,因此我无法获取坐标。我从Play Market下载了onLocationChanged
(按照@ Li3ro的建议)看到卫星可见,但没有固定信号。我无法在建筑物内接收到信号。
即使是独立的地图也无法接收坐标,而户外的则可以。因此,走开后,我可以在应用程序中找到我的协调人。
另请参阅https://stackoverflow.com/a/27828929/2914140,其中提到了优先级和错误识别(如果找不到协调人,则在一段时间后禁用GPS)。
答案 13 :(得分:0)
这可能是由于您的手机设置导致的。在手机的“位置”设置中,如果“位置服务模式”设置为“仅GPS”,则在有GPS修复功能时,OnLocationChanged回调电话将呼叫。通过选择“使用GPS,WI-FI和移动网络”选项,将通过使用这三个提供商来确定位置。这将花费更少的时间来定位您的设备位置。 ***访问位置服务的路径可能是将设备更改为设备。 谢谢
答案 14 :(得分:0)
关闭位置后,这发生在我身上。不是应用程序的位置权限,而是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();
}
来自here的解决方案。
您可能还需要先关闭GPS,然后再打开,以触发对话框以提高定位精度:
答案 15 :(得分:0)
就我而言,即使编写了正确的代码,我也没有使用 client.requestLocationUpdates(locationRequest, this, it)
获取位置。
在手机中也启用了 GPS 使用
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
在切换模拟器、构建等方面花费时间后,终于发现位置模式是“仅限设备”,并且没有在模拟器上提供结果。切换到“高精度”并开始工作。