根据GPS状态,可互换使用网络和GPS定位提供程序(Android)

6
如果有人能帮助我,我将不胜感激。我需要在我的应用程序中拥有一个准确的位置跟踪器,并且我希望它像这样运作。当使用网络时,它会找到人的第一个位置,同时我开始请求GPS定位。当GPS给我一个位置时,我不想再听取网络位置。之后,我只想从网络请求位置,仅当GPS未固定(无法给我位置)时。当GPS再次固定时,我想停止听取网络,这就是我想实现的循环,因为GPS更准确,我希望有网络定位作为备份。我看过这篇文章,但我似乎不知道如何将其调整到我的需求。

如何检查GPS接收器的当前状态?

需要您的想法,谢谢Stackoverflow社区提前。

1个回答

1

1. 停止监听网络位置更新: 非常简单。只需调用

your_loc_manager.removeUpdates(network_location_listener);

2.如果GPS提供程序没有提供任何修复程序,则从网络提供程序获取位置

您可以尝试以下类似的方法(而不是计时器,您可以尝试使用GpsStatus Listener...)。

在获取网络提供程序更新的方法中

boolean network_enabled ;
try {
    network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {
    ex.printStackTrace();
}

if(!network_enabled)
    return;

locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 100, networkLocationListener);

return;

获取GPS位置的方法内部。
boolean gps_enabled;
try {
    gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {
    ex.printStackTrace();
}

if(!gps_enabled) {
    // call your method for getting network location updates 
    return;
}

locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 50, locationListenerGps);
new Timer().schedule(new TimerTask() {

    @Override
    public void run() {
        // You should call your method of getting Network locations based on some 
        // condition which would tell whether you really need to ask for network location 

    }
}, 20000 /* Time Value after which you want to stop trying for GPS and switch to Network*/); 

编辑1:

还有,“我不需要知道何时从GPS获取更新,我需要知道何时从网络获取更新(我的意思是我需要知道何时GPS在搜索,而不是何时已定位)。以及如何控制网络和GPS之间的可互换性。”

……如果位置修复丢失,则只需要寻找网络更新,因此我建议调用。

if (hasGPSFix) { 
    Log.i("GPS","Fix Lost (expired)"); 
    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener);
    lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 2000, 10, locationListener); //===> new line which I am suggesting  
} 
hasGPSFix = false;

这样做,您将从网络获取位置更新,而GPS将继续尝试修复。一旦GPS修复完成,hasGPSFix的值将发生变化,并且所述链接中的现有代码将停止寻找网络更新。至少这是我能理解您想要实现的内容。也许我没有完全理解您的意思。
编辑2:这是我处理GPS和NETWORK提供程序的类。
在需要获取位置更新的mapActivity或其他地方,你需要创建一个MyLocation类的实例。同时,为了持续获取位置更新,你需要在调用活动中实现LocationResult接口。public abstract void gotLocation(Location location, boolean isGpsData);将告诉你刚刚收到的更新是来自网络还是GPS。此外,在返回GPS数据时,它会自动关闭网络监听器。如果你想要来自GPS的数据,就需要调用getFineLocation()方法等等。你需要根据你的需求增强给定的代码(例如,当你只想删除网络更新时,你需要增强closeListeners()方法以仅关闭一个提供程序等等),但它提供了你想要的基本实现(当然,还包括GpsStatus.Listener的实现,因此两者结合起来应该能够很好地满足你的需求)。
public class MyLocation {
    LocationManager locManager;
    LocationResult locationResult;
    boolean gps_enabled = false;
    boolean network_enabled = false;

    public boolean getCoarseLocation(Context context, LocationResult result) {
    locationResult = result;
    if(locManager == null)
        locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    try {
        network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    } catch(Exception ex) {
        ex.printStackTrace();
    }

    if(!network_enabled)
        return false;

    locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 100, networkLocationListener);
    return true;
    }

    public boolean getFineLocation(Context context, LocationResult result) {
    locationResult = result;
    if(locManager == null)
        locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    try {
        gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    } catch(Exception ex) {

    }

    if(!gps_enabled)
        return false;//No way to get location data

    locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 100, locationListenerGps);
    return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
    public void onLocationChanged(Location location) {
        locationResult.gotLocation(location,true);
        locManager.removeUpdates(networkLocationListener);
    }
    public void onProviderDisabled(String provider) {}
    public void onProviderEnabled(String provider) {}
    public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

    LocationListener networkLocationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
        locationResult.gotLocation(location,false);
    }
    public void onProviderDisabled(String provider) {}
    public void onProviderEnabled(String provider) {}
    public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

    public void closeListeners() {
    if(locManager == null)
        return;

    if(locationListenerGps != null)
        locManager.removeUpdates(locationListenerGps);
    if(networkLocationListener != null)
        locManager.removeUpdates(networkLocationListener);
    }

    public static abstract class LocationResult {
    public abstract void gotLocation(Location location, boolean isGpsData);
    }

    public static boolean hasNetworkProvider(Context mContext) {
    List<String> myProvidersList = ((LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE)).getProviders(false);
    return myProvidersList.contains("network");
    }

    public static boolean hasGPSProvider(Context mContext) {
    List<String> myProvidersList = ((LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE)).getProviders(false);
    return myProvidersList.contains("gps");
    }
}

那我认为你应该看看这个答案。它几乎做了你想做的事情。他在这里执行的部分 if (hasGPSFix) { Log.i("GPS","Fix Lost (expired)"); lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener); } hasGPSFix = false; 在这里,你应该请求GPS和网络更新。当GPS Fix再次被获取时,相关处理已经存在,这样就可以做到了。 - Rajeev
由于位置监听器与实现位置管理器的类相关,而不是位置管理器本身,因此在网络中删除更新时遇到了困难。我正在考虑一个解决方案,但明天要在工作中尝试一下,我将为每个位置提供程序创建单独的类,如果我从GPS类获取位置,则使用反射方法调用网络类的删除更新。然后,在GPS不再提供位置信息后,我将调用网络的请求更新。但我仍然没有清楚的想法如何估计GPS状态是否已固定。 - Rubin Basha
我认为你不需要为每个提供者创建单独的类。你需要做的是维护每个提供者及其监听器的单独实例。目前我无法访问我的代码,当我使用工作电脑时可以向你展示我的实现。请查看我的答案中的新编辑,因为它很大,所以不要放在评论中。 - Rajeev
我现在最大的问题可能是找不到一种方法来忽略网络位置当 GPS 打开时,并在 GPS 未固定时重新开始监听它们。我尝试创建两个位置管理器,一个用于网络,一个用于 GPS,但当我使用 remove updates 方法时,它会删除监听器本身,而不是特定 locationManager 的更新,尽管我还有很多尝试。非常感谢您的努力,知道有很多人喜欢帮助别人就是一种愉悦。 - Rubin Basha
嗨,Rubin,很抱歉回复晚了,但我想我们处于不同的时区,有时无法避免。我已经更新了我的答案,并在EDIT 2中给出了同时使用两个位置提供程序的实现方式。您需要根据自己的目的进行改进。是的,您需要尝试很多东西,但嘿,那就是有趣的部分...不是吗? :-) - Rajeev
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接