【问题标题】:OnLocationChanged callback is never calledOnLocationChanged 回调永远不会被调用
【发布时间】:2012-02-18 22:12:48
【问题描述】:

我正在尝试使用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 上看到的东西。另外,作为旁注,我已经能够使用 API 9 中提供的requestSingleUpdate 并按照指南A Deep Dive into Location 使其在 2.3 设备上工作,但我需要它在 2.1 或 2.2 及更高版本上工作使用旧的 SDK。因此,如果您有任何提示或想了解更多信息,请告诉我。提前致谢。

【问题讨论】:

  • 虽然已经很晚了但是希望这个评论可以帮到别人,看看这个链接:lengrand.fr/2013/10/…
  • 我的 OnLocationChanged() 在我的真实手机上运行时也不会被调用。但是,当我在模拟器中运行它时,它可以工作(当然给出了旧金山谷歌总部的 GPS 位置)。这怎么可能?即使我的手机没有 GPS 接收,也应该调用 OnLocationChanged()(每 5000 毫秒)。不会发生。有人吗?

标签: android geolocation locationmanager


【解决方案1】:

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

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 更新。

【讨论】:

  • 这几乎成功了,我认为它有效,因为它在 MyTouch 4G 上有效,我不断更新后更新。然后我尝试了另一台设备(MyTouch 3G),但它不再工作了。我注意到,在仿生设备等更好的设备上,GPS 工作得非常快,但在低端手机上,我似乎永远无法让它工作。低端手机的GPS真的那么差吗?还是我还缺少其他东西?
  • 简化有所帮助,但事实证明,在 MyTouch 3G 上,我必须先连接到 WiFi 网络才能获得位置
  • 这没什么区别
  • 伙计,你真了不起。非常感谢。
  • 为了避免回调开销/电池消耗,我建议在调用 onLocationChanged 时取消注册回调 locationManager.removeUpdates(this)
【解决方案2】:

替换

LocationManager.GPS_PROVIDER

LocationManager.NETWORK_PROVIDER

解决了我的问题。

这是我的位置管理器的代码 sn-p

 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 应用。
【解决方案3】:

GPS Provider 将在设备处于低电量或使用省电模式时禁用,在这种情况下我们无法接收onLocationChanged

GPS 提供商几乎不会返回如果您呆在房屋或建筑物内(只能在室外正常工作)

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

https://developer.android.com/guide/topics/location/strategies.html#Updates

要向 GPS 提供商请求位置更新,请使用 GPS_PROVIDER 而不是 NETWORK_PROVIDER。您还可以请求位置更新 从 GPS 和网络位置提供商通过调用 requestLocationUpdates() 两次——一次用于 NETWORK_PROVIDER,一次用于 GPS_PROVIDER。

【讨论】:

  • 在我的情况下,PRIORITY_HIGH_ACCURACY 优先网络提供商自动关闭,而在PRIORITY_BALANCED_POWER_ACCURACY 中,它找到了我的坐标。所以,去户外后,GPS 在几分钟内就找到了我的设备。
【解决方案4】:

正如 Steve Blackwell 所写,您的设置很好。您可以尝试的是了解您是否 100% 拥有 GPS 固定信号!我安装了一个不错的GPS Tester application (from the play store),它会告诉你是否有修复,你连接到哪些卫星,连接强度是多少。 这就是我的 OnLocationChanged() 从未调用过的原因。我尝试在建筑物内运行它:\

祝你好运!

【讨论】:

  • 感谢分享这么棒的应用程序,我安装了它,发现在某些地方我的 gps 位置没有自动更新(在我的应用程序中)
  • 很棒的工具,那个 GPS 测试应用程序,所以我可以在我的设备上看到它显示 GPS:NO Fix。我想这意味着没有固定的 GPS 信号,对吧?
  • 是的。这基本上意味着“我没有足够的卫星连接来计算三角测量来设置你的位置”..
  • 谢谢!我了解到我的新廉价设备无法与卫星建立连接。因此,在建筑物中,我看不到PRIORITY_HIGH_ACCURACY 的 GPS 坐标(而在三星 Galaxy S4 上它可以在几秒钟内找到)。我在一条街上走后,它找到了坐标,但在几分钟内。
【解决方案5】:

很抱歉碰到这么老的帖子,但这可能对其他人来说很方便,因为这个问题在谷歌搜索中的排名相对较高。

我遇到了类似的问题,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;

}
};

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

【讨论】:

  • 这也正是我的问题。相同的场景和线索。希望 Google 能修复有缺陷的 Android,但话说回来,它不是 Android,而是 iOS。
【解决方案6】:

我遇到了类似的问题。我有权限,正确请求服务,但没有更新。事实证明,我所要做的只是等待。当我在互联网上搜索问题时,我运行了应用程序,几分钟后它才开始接收更新。然后,即使我杀死了应用程序并再次运行它,更新也会立即出现——我猜这是系统问题,一些优化,可能是因为设备根本没有移动(顺便说一句。这不是什么糟糕的设备,是像素)。

【讨论】:

    【解决方案7】:
    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);
            }
    }
    

    【讨论】:

      【解决方案8】:

      我遇到了同样的问题。我得到 getLastKnownLocation 为空。当我重新启动设备和设备中的定位服务时,问题得到解决。

      【讨论】:

      • 我遇到了同样的问题,但我知道有些设备也需要时间/移动来获取位置 lat-lon...我的 nexus 没有获取 lat-lon 而 moto 能够获取跨度>
      【解决方案9】:

      如果你正在尝试使用NETWORK_PROVIDER,那真的很难测试:

      • 在模拟器上:从不工作
      • 在真实设备上:只有 getLastKnownLocation() 有效,要接收 onLocationChanged(),您必须使用移动数据并外出时冒着被强盗丢失手机的风险:P

      我猜原因是它只是网络提供商的位置而不是您的设备本身,并且网络提供商永远不会移动,所以 onLocationChanged() 永远不会调用。只有在移动数据和 wifi 之间切换时才会发生这种情况,反之亦然。如果我错了,请纠正我。

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

      我用 NETWORK_PROVIDER 进行了几个小时的测试,但没有任何结果,希望我的建议对您有所帮助。

      【讨论】:

        【解决方案10】:

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

        【讨论】:

          【解决方案11】:

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

          【讨论】:

            【解决方案12】:

            我有 2 台设备:Samsung Galaxy S4 (Android 5.0.1) 和 Vertex Win (Android 8.1)。

            在三星上,一切正常且快速,GPS 坐标被找到,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)。

            【讨论】:

              【解决方案13】:

              这应该是由于您的手机设置造成的。在手机定位设置中,如果定位服务模式设置为仅 GPS,则在有 GPS Fix 时调用 OnLocationChanged 回调。通过选择使用 GPS、WI-FI 和移动网络选项,将使用这三个提供商确定位置。这将花费更少的时间来定位您的设备位置。 ***访问位置服务的路径可能会更改设备到设备。 谢谢

              【讨论】:

                【解决方案14】:

                当位置关闭时,这发生在我身上。不是应用程序的位置权限,而是 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】:

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

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

                  在花时间切换模拟器、构建等之后,终于发现位置模式是“仅限设备”并且它没有在模拟器上提供结果。切换到“高精度”并开始工作。

                  【讨论】:

                    猜你喜欢
                    • 2023-03-18
                    • 2017-01-20
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-07-22
                    • 2013-01-02
                    • 2012-08-19
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多