【问题标题】:LocationListener of NETWORK_PROVIDER is enabled but , onLocationChanged is never calledNETWORK_PROVIDER 的 LocationListener 已启用,但永远不会调用 onLocationChanged
【发布时间】:2013-03-22 18:27:57
【问题描述】:

我正在开发一个应用程序,该应用程序可以在服务中的 6 分钟和 6 分钟内全天获取手机的位置,它工作正常,但有时网络提供商侦听器的方法 OnLocationChanged 停止被调用,我没有不知道为什么。

它由于某种原因停止被调用,但提供程序已启用并且列表器正在工作,当我手动启用或禁用提供程序时,onProviderEnabledonProviderDisabled 被调用。

NETWORK_PROVIDER 会发生这种情况,GPS_PROVIDER 效果很好。

听众:

LocationListener locationListenerGPS = new LocationListener() {
        // @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO locationListenerGPS onStatusChanged
            Log.d(TAG, "Provedor trocado");
        }

        // @Override
        public void onProviderEnabled(String provider) {
            Log.w(TAG, "PROVEDOR " + provider + " HABILITADO!");
        }

        // @Override
        public void onProviderDisabled(String provider) {
            Log.w(TAG, "PROVEDOR " + provider + " DESABILITADO!");
        }

        // @Override
        public void onLocationChanged(Location location) {

            longitudeGPS = location.getLongitude();
            latitudeGPS = location.getLatitude();
            Log.d(TAG,"LocationChangedGPS LAT: "+latitudeGPS+" longi: "+longitudeGPS);
            gpsComSinal = true;
        }
    };

    LocationListener locationListenerNET = new LocationListener() {

        // @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO locationListenerNET onStatusChanged
            Log.d("Contele", "Provedor foi mudado");
        }

        // @Override
        public void onProviderEnabled(String provider) {
            Log.i(TAG, "PROVEDOR " + provider + " HABILITADO!");
        }

        // @Override
        public void onProviderDisabled(String provider) {
            Log.i(TAG, "PROVEDOR " + provider + " DESABILITADO!");
        }

        @Override
        public void onLocationChanged(Location location) {
            longitudeNET = location.getLongitude();
            latitudeNET = location.getLatitude();
            Log.d(TAG,"LocationChangedNET LAT: "+latitudeNET+" longi: "+longitudeNET);
            netComSinal = true;
        }
    };

代码:

public void initProviders() {

        localizacao = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);


        localizacao.removeUpdates(locationListenerNET);
        localizacao.removeUpdates(locationListenerGPS);

        localizacao.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                locationListenerGPS);

        localizacao.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,
                0, locationListenerNET);

        Log.d(TAG,"EsperaGPS");
        Handler esperaGPS = new Handler() {
            public void handleMessage(Message msg) {

                requestGPS();
            }
        };

        Message msgEsperaGPS = Message.obtain();
        msgEsperaGPS.what = 0;
        esperaGPS.sendMessageDelayed(msgEsperaGPS, 35000);
    }



    public void requestGPS() {
            if (gpsComSinal) {
                Log.d(TAG,"PEGO SINAL DE GPS");
                rastreio = "GPS";
                longitude = longitudeGPS;
                latitude = latitudeGPS;
                Log.d(TAG, "Utilizando provedor GPS.");
                localizacao.removeUpdates(locationListenerGPS);
                localizacao.removeUpdates(locationListenerNET);

            } else {
                Log.d(TAG,"Sem GPS... pegar NEt");
                // Setando os valores para usar network
                localizacao.removeUpdates(locationListenerGPS);
                localizacao.removeUpdates(locationListenerNET);
                localizacao
                        .requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                                0, 0, locationListenerNET);
                Log.d(TAG,"EsperaNET");

                        requestNET();
            }
        }

    public void requestNET() {
            if (netComSinal) {
                Log.d(TAG,"PEGO SINAL DE NET");
                rastreio = "NET";
                longitude = longitudeNET;
                latitude = latitudeNET;
                Log.d(TAG, "Utilizando provedor NET.");
                localizacao.removeUpdates(locationListenerNET);

            } else {
                localizacao.removeUpdates(locationListenerGPS);
                localizacao.removeUpdates(locationListenerNET);
                Log.d(TAG,"Sem sinal");
            }
        }

三星 Galaxy S3 中的报告:

仍然连续 4 天收到“Sem sinal”。

Galaxy Y 和 LG Optimus l5 已经出现此问题

我进行了另一项测试,看看其他应用程序是否获得了 NET 位置,我发现它们通过了同样的问题,它们无法仅通过 GetLastknowLocation 获得 NET 位置;测试我使用 Galaxy S3 解决了这个问题,并禁用了 GPS Provider。 (在 Cerberus 中测试)。

我找不到任何解释为什么 NETWORKSLOCATIONS 听众停止给出位置,但这可能是因为它不应该连续工作 2 或 3 天。

我已经对其他应用程序进行了一些测试,看看这个问题是否只是在我的应用程序中发生,我发现它们正在通过同样的问题,例如在 Cerberus 中:

我在手机 (Galaxy S3) 中因“Sem sinal”问题禁用了 GPS 提供程序,看看:

我的报告:

和 Cerberus(打印于 2013 年 5 月 14 日)报告:

但是当我打开谷歌地图时,它似乎工作正常,我试图移动到一个较远的地方,看看它是否会显示GetLastknowLocation,但是没有,谷歌地图把我放在了正确的地方,所以我意识到谷歌地图正在使用motionevent在地图中移动我;

同时打印 Google Maps 的 Log 以获取 NetWorkProvider:

正常情况:

句号:

【问题讨论】:

  • 这是因为网络提供商提供的不是您的位置,而是塔/bts 小区位置。我可能错了,但我认为如果你移动得足够多,你可能会捕捉到其他塔/bts 单元,并且你会在该网络侦听器中获得新位置。
  • 已经过这个了,我试着移动了2000米+但是没有成功,如果我重启手机应用程序正常工作4或3天,在某些设备上这个问题从未发生过。我的 Galaxy S3 连续 2 天出现此问题,但它没有获得单一的网络位置,只有 GPS。
  • 似乎设备 NetworkLocation Provider 坏了..我在一些 HTC 设备上也遇到过类似的问题,然后在网上搜索 HTC GPS 问题,发现很多用户抱怨 GPS 无法正常工作..跨度>
  • @Akhil 我认为这不是设备问题,因为它之前发生在其他手机上。

标签: android geolocation gps locationmanager locationlistener


【解决方案1】:

我遇到过与网络提供商类似的问题,唯一的解决方案是强制设备重启。 尽管谷歌地图总是显示正确的位置,因为它使用了除了网络位置提供者之外的其他传感器信息。

但这里是好消息,不是很久以前 Google 通过其 Google Play Service Framework 引入了 Fused Location Provider api,它比 GPS / 网络位置提供程序超级容易使用。

兼容 API 级别 8,现在当我遇到网络提供商这个奇怪的问题时,同时融合位置给了我准确的位置(无需重启设备)。

我已经提交了一个工作FusedLocation Test Project here,你可以自己克隆和测试..

下面是sn-p的代码:-

package com.example.fusedLoctionTest.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationRequest;

public class FusedLocationService extends Service implements GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener{
    private static final LocationRequest REQUEST = LocationRequest.create()
            .setInterval(0)
            .setFastestInterval(0)
            .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    public static final String LOCATION_RECEIVED = "fused.location.received";
    private Long now;

    private LocationClient mLocationClient;
    private final Object locking = new Object();
    private Runnable onFusedLocationProviderTimeout;
    private Handler handler = new Handler();

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        now = Long.valueOf(System.currentTimeMillis());
        mLocationClient = new LocationClient(this, this, this);
        mLocationClient.connect();
        return START_STICKY;
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d("FusedLocationService", "Fused Location Provider got connected successfully");
        mLocationClient.requestLocationUpdates(REQUEST,this);
        onFusedLocationProviderTimeout = new Runnable() {
            public void run() {
                Log.d("FusedLocationService", "location Timeout");

                Location lastbestStaleLocation=getLastBestStaleLocation();
                sendLocationUsingBroadCast(lastbestStaleLocation);

                if(lastbestStaleLocation!=null)
                    Log.d("FusedLocationService", "Last best location returned ["+lastbestStaleLocation.getLatitude()+","+lastbestStaleLocation.getLongitude()+"] in "+(Long.valueOf(System.currentTimeMillis())-now)+" ms");

                if(mLocationClient.isConnected())
                    mLocationClient.disconnect();
            }
        };
        handler.postDelayed(onFusedLocationProviderTimeout, 20000);//20 sec
    }

    private void sendLocationUsingBroadCast(Location location) {
        Intent locationBroadcast = new Intent(FusedLocationService.LOCATION_RECEIVED);
        locationBroadcast.putExtra("LOCATION", location);
        locationBroadcast.putExtra("TIME", Long.valueOf(System.currentTimeMillis()-now) +" ms");
        LocalBroadcastManager.getInstance(this).sendBroadcast(locationBroadcast);
        stopSelf();
    }

    @Override
    public void onDisconnected() {
        Log.d("FusedLocationService","Fused Location Provider got disconnected successfully");
        stopSelf();
    }

    @Override
    public void onLocationChanged(Location location) {
        synchronized (locking){
            Log.d("FusedLocationService", "Location received successfully ["+location.getLatitude()+","+location.getLongitude()+"] in "+(Long.valueOf(System.currentTimeMillis()-now))+" ms");

            handler.removeCallbacks(onFusedLocationProviderTimeout);
            if(mLocationClient.isConnected())
                mLocationClient.removeLocationUpdates(this);

            sendLocationUsingBroadCast(location);

            if(mLocationClient.isConnected())
                mLocationClient.disconnect();
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d("FusedLocationService", "Error connecting to Fused Location Provider");
    }

    public Location getLastBestStaleLocation() {
        Location bestResult = null;
        LocationManager locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Location lastFusedLocation=mLocationClient.getLastLocation();
        Location gpsLocation = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        Location networkLocation = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        if (gpsLocation != null && networkLocation != null) {
            if (gpsLocation.getTime() > networkLocation.getTime())
                bestResult = gpsLocation;
        } else if (gpsLocation != null) {
            bestResult = gpsLocation;
        } else if (networkLocation != null) {
            bestResult = networkLocation;
        }

        //take Fused Location in to consideration while checking for last stale location
        if (bestResult != null && lastFusedLocation != null) {
            if (bestResult.getTime() < lastFusedLocation.getTime())
                bestResult = lastFusedLocation;
        }

        return bestResult;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

【讨论】:

  • 我已经实现了类似的东西,当我的应用程序进入后台时可以接收位置更新。但是,当我销毁我的应用程序(服务仍在运行)时,我不再收到位置更新。您的应用程序也会发生同样的情况。任何想法为什么?
  • R...重启?多么可怕的失败,谷歌。
  • google play services library 将我的 dex 方法数最大化。
  • 此答案已被弃用,LocationClient 和 GooglePlayServicesClient 正在更改为 GoogleApiClient see this 可能会有所帮助
  • 挣扎了几个小时后,我的解决办法就是站起来,走出去。!
【解决方案2】:

我有完全相同的问题,我唯一的解决方案是重新启动设备。有趣的是,除了谷歌地图,没有一个应用程序有位置信息。
Google 地图应用程序以某种方式找到了位置!..

附言在服务中使用LocationListener,所以绝对不是坏引用、死对象等问题。

【讨论】:

  • 是的,这有点神秘,但我认为谷歌地图使用加速度计来处理这个问题。
  • 就我而言,当其他人收到时,我的应用不会在一部特定手机上收到任何 onLocationChanged 回调。我注意到与 m190 相同的事情:不知何故,谷歌地图正在获取当前位置,而我的应用程序被卡住了,只能获取最后已知的位置,这些位置已经很老了。重新启动设备最终解决了问题。很想知道 Google 地图的不同之处...
【解决方案3】:

我仍然有这个问题。但我仍在寻找答案,我尝试在 NETWORK_PROVIDER 的侦听器中实现这一点:

public void onStatusChanged(final String provider, final int status, final Bundle extras) {
    switch( status ) {
    case LocationProvider.AVAILABLE:
                // ...
        break;
    case LocationProvider.OUT_OF_SERVICE:
                // ...
        break;
    case LocationProvider.TEMPORARILY_UNAVAILABLE:
                // ...
        break;
    }
}

因为:OUT_OF_SERVICE 如果提供商停止服务,并且预计在不久的将来不会改变; TEMPORARILY_UNAVAILABLE 如果提供者暂时不可用但预计很快就会可用;如果提供程序当前可用,则为 AVAILABLE。 onStatusChanged

我认为 OUT_OF_SERVICE 是我的问题,目前还没有解决方案,只是重新启动设备,然后我尝试在发生这种情况时进行一些报告,当发生这种情况时,我要求用户重新启动设备,但是很少有设备会收到此状态。

【讨论】:

    【解决方案4】:

    似乎是一个开放的错误,Android 开源项目报告的网络提供商问题,问题跟踪器:https://code.google.com/p/android/issues/detail?id=57707。 简而言之:2013 年 7 月 17 日报告的问题 - 上一篇博客 2015 年 1 月 7 日,问题出现在 Android 4.1.x 中,出现在各种设备中,“在最新的 Play 服务库中未解决”,博客中没有建议的解决方法。

    【讨论】:

    • 为什么他们将其标记为过时...问题从未得到解决。
    【解决方案5】:

    我理解我们的问题中的一些内容;您调用 requestGPS 方法,然后发现它的位置。如果启用了 gps,则通过 gps 获取。 Othervise gott via NET。当调用 requestGPS 和 control provider 比获取 lat-lang 但删除更新时。(不要调用,因为你删除了更新触发器);

    if (gpsComSinal) {
        Log.d(TAG,"PEGO SINAL DE GPS");
        rastreio = "GPS";
        longitude = longitudeGPS;
        latitude = latitudeGPS;
    
        Log.d(TAG, "Utilizando provedor GPS.");
        // if you remove update don't call onLocationChanged
        localizacao.removeUpdates(locationListenerGPS); 
        localizacao.removeUpdates(locationListenerNET);
    } else {
        Log.d(TAG,"Sem GPS... pegar NEt");
        // Setando os valores para usar network
        localizacao.removeUpdates(locationListenerGPS);
        localizacao.removeUpdates(locationListenerNET);
        localizacao.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                                           0, 0, locationListenerNET);
        Log.d(TAG,"EsperaNET");
        requestNET();
    }
    

    【讨论】:

    • 我同意你的观点,有一些无用的 removeUpdates,但是在这一点上,如果(gpsComSinal)我已经等了 35 秒听 NetProvicer 和 GPSProvider 并保存了他们的位置,因为我想要位置6 和 6 分钟,我想节省电池。所以这个 removeUpdates 不是问题,因为 6 分钟后我再次请求他们的位置。
    【解决方案6】:

    当手机的 GPS 正在运行并接收到信号时,NETWORK_PROVIDER 不会更新。如果您关闭 GPS 并强制手机从网络中获取其位置,那么您将再次开始获取更新。

    【讨论】:

      【解决方案7】:

      我认为这是因为您的应用在后台被“杀死”。我以前遇到过这个问题,我通过在服务中移动 LocationListener 的创建来解决它。一定要保留对侦听器的引用。它可能会解决问题。

      【讨论】:

      • 我有一个在该服务中运行 6 和 6 分钟的服务,我为 GPS 和 NET 创建了 LocationListener,并且没有错误,应用程序也没有被杀死,因为它仍然得到GPS 位置,如果我出去,GPS 提供商的 OnlocationChanged 会返回 LAT 和 LONGITUDE,但即使我有 WIFI 连接或 3G,NET 仍然“死”。
      【解决方案8】:

      我遇到过这个问题,当您禁用 GPS 时,我发现网络提供商无法在某些 Android 设备中工作,因为如果未启用 GPS,它们会阻止访问位置数据。

      我在很多设备上都试过了 1. 联想k6 note (screen shot1, screen shot2) 2.小​​米米9tscreen shot1 3. 谷歌 Pixel 1 和 Pixel 2

      所以有些设备需要启用 GPS 才能从 LocationManager.NETWORK_PROVIDER 访问位置,如果不启用 GPS,您将无法获取位置数据

      【讨论】:

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